2024-08-26 22:01:23 +00:00
|
|
|
package;
|
|
|
|
|
|
|
|
// I don't think we can import `funkin` classes here. Macros? Recursion? IDK.
|
|
|
|
import hxp.*;
|
|
|
|
import lime.tools.*;
|
|
|
|
import sys.FileSystem;
|
2025-04-17 11:22:45 +00:00
|
|
|
import sys.io.File;
|
2025-04-27 11:33:34 +00:00
|
|
|
import haxe.io.Path;
|
2025-04-17 11:22:45 +00:00
|
|
|
import haxe.ds.Map;
|
2024-08-26 22:01:23 +00:00
|
|
|
|
|
|
|
using StringTools;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This HXP performs the functions of a Lime `project.xml` file,
|
|
|
|
* but it's written in Haxe rather than XML!
|
|
|
|
*
|
|
|
|
* This makes it far easier to organize, reuse, and refactor,
|
|
|
|
* and improves management of feature flag logic.
|
|
|
|
*/
|
|
|
|
@:nullSafety
|
2025-05-11 23:43:45 +00:00
|
|
|
class Project extends HXProject
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// METADATA
|
|
|
|
//
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The game's version number, as a Semantic Versioning string with no prefix.
|
|
|
|
* REMEMBER TO CHANGE THIS WHEN THE GAME UPDATES!
|
|
|
|
* You only have to change it here, the rest of the game will query this value.
|
|
|
|
*/
|
2025-07-21 23:35:47 +00:00
|
|
|
static final VERSION:String = "0.7.3";
|
2025-05-11 23:43:45 +00:00
|
|
|
|
2025-06-16 19:34:03 +00:00
|
|
|
/**
|
|
|
|
* The build's number and version code.
|
|
|
|
* Used when publishing the game to mobile app stores. Should increment with each patch.
|
|
|
|
*/
|
|
|
|
static final BUILD_NUMBER:Int = 2;
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* The game's name. Used as the default window title.
|
|
|
|
*/
|
|
|
|
static final TITLE:String = "Friday Night Funkin'";
|
|
|
|
|
2025-06-16 19:34:03 +00:00
|
|
|
/**
|
|
|
|
* A package name used for identifying the app on various app stores.
|
|
|
|
*/
|
|
|
|
static final PACKAGE_NAME:String = "me.funkin.fnf";
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* The name of the generated executable file.
|
|
|
|
* For example, `"Funkin"` will create a file called `Funkin.exe`.
|
|
|
|
*/
|
|
|
|
static final EXECUTABLE_NAME:String = "Funkin";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The relative location of the source code.
|
|
|
|
*/
|
|
|
|
static final SOURCE_DIR:String = "source";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The fully qualified class path for the game's preloader.
|
|
|
|
* Particularly important on HTML5 but we use it on all platforms.
|
|
|
|
*/
|
|
|
|
static final PRELOADER:String = "funkin.ui.transition.preload.FunkinPreloader";
|
|
|
|
|
2025-04-16 11:29:08 +00:00
|
|
|
/**
|
|
|
|
* The fully qualified class path for the entry point class to execute when launching the game.
|
|
|
|
* It's where `public static function main():Void` goes.
|
|
|
|
*/
|
|
|
|
static final MAIN_CLASS:String = "Main";
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* The company name for the game.
|
|
|
|
* This appears in metadata in places I think.
|
|
|
|
*/
|
|
|
|
static final COMPANY:String = "The Funkin' Crew";
|
2024-08-26 22:01:23 +00:00
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* The app's localization languages.
|
2024-08-26 22:01:23 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final LANGUAGES:Array<String> = ["en"];
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* The contents of the user's environment config.
|
|
|
|
* Read from the local `.env` file. Used for storing API keys.
|
2025-05-11 23:43:45 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static var envConfig:Null<Map<String, Dynamic>> = null;
|
2025-05-11 23:43:45 +00:00
|
|
|
|
2025-06-16 19:34:03 +00:00
|
|
|
//
|
|
|
|
// MOBILE METADATA
|
|
|
|
//
|
2025-05-11 23:43:45 +00:00
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* The app's minimal Android SDK version.
|
2025-05-11 23:43:45 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final ANDROID_MINIMUM_SDK_VERSION:Int = 28;
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-04-16 11:29:08 +00:00
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* The app's target Android SDK version.
|
2025-04-16 11:29:08 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final ANDROID_TARGET_SDK_VERSION:Int = 35;
|
2025-04-16 11:29:08 +00:00
|
|
|
|
2025-07-10 13:26:01 +00:00
|
|
|
static final ANDROID_EXTENSIONS:Array<String> = ["funkin.extensions.CallbackUtil"];
|
|
|
|
|
2025-06-16 19:34:03 +00:00
|
|
|
//
|
|
|
|
// ASTC COMPRESSION
|
|
|
|
//
|
2025-04-29 00:56:09 +00:00
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* The quality of the compression process.
|
|
|
|
* This doesn't exactly reduce the quality of the outputted texture..
|
|
|
|
* But it changes how hard the CPU gotta work to maintin the quality and details of the image while compressing.
|
|
|
|
* possible values: fastest, fast, medium, thorough, exhaustive.
|
2025-05-02 20:26:55 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static var ASTC_QUALITY:String = "medium";
|
2025-05-02 20:26:55 +00:00
|
|
|
|
2025-06-03 09:55:35 +00:00
|
|
|
/**
|
|
|
|
* The team ID to use for the iOS app. Configured in XCode.
|
|
|
|
*/
|
2025-06-08 01:16:55 +00:00
|
|
|
static var IOS_TEAM_ID:String = "Z7G7AVNGSH";
|
2025-06-03 09:55:35 +00:00
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
/**
|
|
|
|
* The block size of the ASTC compressed textures.
|
2025-05-03 13:32:36 +00:00
|
|
|
* Higher block size means lower quality and lighter file size for the generated compressed textures.
|
|
|
|
* possible block sizes: 4x4, 4x6, 6x6, 8x8 ... 12x12.
|
2025-06-03 06:54:53 +00:00
|
|
|
*/
|
2025-06-03 22:41:25 +00:00
|
|
|
static var ASTC_BLOCKSIZE:String = "10x10";
|
2025-05-03 13:32:36 +00:00
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* A list of asset file globs to exclude from ASTC compression when creating optimized mobile builds.
|
2025-06-03 06:54:53 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static var astcExcludes:Array<String> = [];
|
|
|
|
|
|
|
|
//
|
|
|
|
// BUILD SCRIPTS
|
|
|
|
//
|
2025-04-30 04:31:31 +00:00
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* Path to the Haxe script run before building the game.
|
2025-06-03 06:54:53 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final PREBUILD_HX:String = "source/Prebuild.hx";
|
2025-04-30 04:31:31 +00:00
|
|
|
|
2025-05-03 13:32:36 +00:00
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* Path to the Haxe script run after building the game.
|
2025-06-03 06:54:53 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final POSTBUILD_HX:String = "source/Postbuild.hx";
|
2025-05-03 13:32:36 +00:00
|
|
|
|
2025-04-16 11:29:08 +00:00
|
|
|
//
|
2025-06-16 19:34:03 +00:00
|
|
|
// ASSET FILTERS
|
2025-04-16 11:29:08 +00:00
|
|
|
//
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* Asset path globs to always exclude from asset libraries.
|
2025-05-11 23:43:45 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final EXCLUDE_ASSETS:Array<String> = [".*", "cvs", "thumbs.db", "desktop.ini", "*.hash", "*.md"];
|
2025-05-11 23:43:45 +00:00
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* Asset path globs to exclude on web platforms.
|
2025-05-11 23:43:45 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final EXCLUDE_ASSETS_WEB:Array<String> = ["*.ogg"];
|
2025-05-11 23:43:45 +00:00
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* Asset path globs to exclude on native platforms.
|
2025-05-11 23:43:45 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final EXCLUDE_ASSETS_NATIVE:Array<String> = ["*.mp3"];
|
|
|
|
|
2025-06-14 03:00:33 +00:00
|
|
|
/**
|
|
|
|
* Asset path globs to exclude on platforms with `CENSOR_EXPLETIVES` enabled.
|
|
|
|
*/
|
|
|
|
static final EXCLUDE_ASSETS_CENSORED:Array<String> = ["stressCutscene.mp4", "stressPicoCutscene.mp4", "darnellCutscene.mp4"];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Asset path globs to exclude on platforms with `CENSOR_EXPLETIVES` disabled.
|
|
|
|
*/
|
|
|
|
static final EXCLUDE_ASSETS_UNCENSORED:Array<String> = [
|
|
|
|
"stressCutscene-censored.mp4",
|
|
|
|
"stressPicoCutscene-censored.mp4",
|
|
|
|
"darnellCutscene-censored.mp4"
|
|
|
|
];
|
|
|
|
|
2025-06-16 19:34:03 +00:00
|
|
|
//
|
|
|
|
// BUILD FLAGS
|
|
|
|
// Inverse build flags are automatically populated.
|
|
|
|
//
|
|
|
|
|
|
|
|
/**
|
|
|
|
* `-DCENSOR_EXPLETIVES`
|
|
|
|
* If enabled, specifically disable "sexual explitives" in the game.
|
|
|
|
* This will forcibly censor these words (even if naughtyness is enabled), while leaving other swears.
|
|
|
|
*
|
|
|
|
* NOTE: This is needed because the Android platform specifically hates "fuck" and "cunt",
|
|
|
|
* but is fine with other naughtyness such as "cock", "asshole", implied sex, cigarettes, etc.
|
|
|
|
*/
|
|
|
|
static final CENSOR_EXPLETIVES:FeatureFlag = "CENSOR_EXPLETIVES";
|
2025-05-11 23:43:45 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* `-DEMBED_ASSETS`
|
|
|
|
* Whether to embed all asset libraries into the executable.
|
2025-06-16 19:34:03 +00:00
|
|
|
* Enabled on web, usually disabled on desktop.
|
2025-05-11 23:43:45 +00:00
|
|
|
*/
|
|
|
|
static final EMBED_ASSETS:FeatureFlag = "EMBED_ASSETS";
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-04-30 04:31:31 +00:00
|
|
|
/**
|
|
|
|
* `-DEXCLUDE_ARMV7`
|
|
|
|
* If this flag is enabled, armv7 won't be compiled when building android.
|
|
|
|
*/
|
|
|
|
static final EXCLUDE_ARMV7:FeatureFlag = "EXCLUDE_ARMV7";
|
|
|
|
|
2025-06-16 19:34:03 +00:00
|
|
|
/**
|
|
|
|
* `-DGITHUB_BUILD`
|
|
|
|
* If this flag is enabled, the game will use the configuration used by GitHub Actions
|
|
|
|
* to generate playtest builds to be pushed to the launcher.
|
|
|
|
*
|
|
|
|
* This is generally used to forcibly enable debugging features,
|
|
|
|
* even when the game is built in release mode for performance.
|
|
|
|
*/
|
|
|
|
static final GITHUB_BUILD:FeatureFlag = "GITHUB_BUILD";
|
|
|
|
|
2024-08-26 22:01:23 +00:00
|
|
|
/**
|
|
|
|
* `-DHARDCODED_CREDITS`
|
|
|
|
* If this flag is enabled, the credits will be parsed and encoded in the game at compile time,
|
|
|
|
* rather than read from JSON data at runtime.
|
|
|
|
*/
|
|
|
|
static final HARDCODED_CREDITS:FeatureFlag = "HARDCODED_CREDITS";
|
|
|
|
|
2025-06-16 19:34:03 +00:00
|
|
|
/**
|
|
|
|
* `-DPRELOAD_ALL`
|
|
|
|
* Whether to preload all asset libraries.
|
|
|
|
* Disabled on web, enabled on desktop.
|
|
|
|
*/
|
|
|
|
static final PRELOAD_ALL:FeatureFlag = "PRELOAD_ALL";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* `-DREDIRECT_ASSETS_FOLDER`
|
|
|
|
* If this flag is enabled, the game will redirect the `assets` folder from the `export` folder
|
|
|
|
* to the `assets` folder at the root of the workspace.
|
|
|
|
* This is useful for ensuring hot reloaded changes don't get lost when rebuilding the game.
|
|
|
|
*/
|
|
|
|
static final REDIRECT_ASSETS_FOLDER:FeatureFlag = "REDIRECT_ASSETS_FOLDER";
|
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
/**
|
|
|
|
* `-DTESTING_ADS`
|
|
|
|
* If this flag is enabled, mobile advertisements will use testing mode.
|
|
|
|
*/
|
|
|
|
static final TESTING_ADS:FeatureFlag = "TESTING_ADS";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* `-DUNLOCK_EVERYTHING`
|
|
|
|
* If this flag is enabled, the game will assume all songs have been beaten and all content is available.
|
|
|
|
*/
|
|
|
|
static final UNLOCK_EVERYTHING:FeatureFlag = "UNLOCK_EVERYTHING";
|
|
|
|
|
2025-06-16 19:34:03 +00:00
|
|
|
//
|
|
|
|
// FEATURE FLAGS
|
|
|
|
// Inverse build flags are automatically populated.
|
|
|
|
//
|
|
|
|
|
|
|
|
/**
|
|
|
|
* `-DFEATURE_COMPRESSED_TEXTURES`
|
|
|
|
* If this flag is enabled, ASTC compressed textures will be used over uncompressed PNGs.
|
2025-06-26 21:54:03 +00:00
|
|
|
* Compressed ASTC textures provide lower memory usage but at the cost of a slightly higher files size & more GPU usage.
|
2025-06-16 19:34:03 +00:00
|
|
|
* ASTC textures are GPU Rendered so they have a few cons:
|
2025-06-26 21:54:03 +00:00
|
|
|
* - Pixel Data of bitmaps cannot be read nor edited directly.
|
2025-06-16 19:34:03 +00:00
|
|
|
* - Some filters specifically the ones in openfl.filters package won't work properly because they directly modify the bitmap pixels.
|
2025-06-26 21:54:03 +00:00
|
|
|
* - ASync loading for GPU Compressed Textures doesn't work due to OpenGL being single-threaded. (Looking online there seem to be some workarounds but it's pretty complicated...).
|
2025-06-16 19:34:03 +00:00
|
|
|
* One thing to note is that ASTC textures aren't available on all platforms:
|
2025-06-26 21:54:03 +00:00
|
|
|
* - For iOS, it's available starting from phones with A8 chips, so anything from iPhone 6 and beyond has it.
|
|
|
|
* - For Android, it's sorta mixed, but mostly any mid range phone that came after 2017 does support ASTC.
|
2025-06-26 22:11:49 +00:00
|
|
|
* - For desktop, it appears to be only supported on Intergrated Graphics from our testing.
|
2025-06-16 19:34:03 +00:00
|
|
|
*/
|
|
|
|
static final FEATURE_COMPRESSED_TEXTURES:FeatureFlag = "FEATURE_COMPRESSED_TEXTURES";
|
2025-06-11 07:30:50 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* `-DFEATURE_DEBUG_FUNCTIONS`
|
|
|
|
* If this flag is enabled, the game will have all playtester-only debugging functionality enabled.
|
|
|
|
* This includes debug hotkeys like time travel in the Play State.
|
|
|
|
* By default, enabled on debug builds or playtester builds and disabled on release builds.
|
|
|
|
*/
|
|
|
|
static final FEATURE_DEBUG_FUNCTIONS:FeatureFlag = "FEATURE_DEBUG_FUNCTIONS";
|
|
|
|
|
2025-06-28 19:03:39 +00:00
|
|
|
/**
|
|
|
|
* `-DFEATURE_RESULTS_DEBUG`
|
|
|
|
* If this flag is enabled, a debug menu for Results screen will be accessible from the debug menu.
|
|
|
|
*/
|
|
|
|
static final FEATURE_RESULTS_DEBUG:FeatureFlag = "FEATURE_RESULTS_DEBUG";
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* `-DFEATURE_DEBUG_TRACY`
|
|
|
|
* If this flag is enabled, the game will have the necessary hooks for the Tracy profiler.
|
|
|
|
* Only enable this if you're using the correct fork of Haxe to support this.
|
|
|
|
* @see https://github.com/HaxeFoundation/hxcpp/pull/1153
|
|
|
|
*/
|
|
|
|
static final FEATURE_DEBUG_TRACY:FeatureFlag = "FEATURE_DEBUG_TRACY";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* `-DFEATURE_DISCORD_RPC`
|
|
|
|
* If this flag is enabled, the game will enable the Discord Remote Procedure Call library.
|
|
|
|
* This is used to provide Discord Rich Presence support.
|
|
|
|
*/
|
|
|
|
static final FEATURE_DISCORD_RPC:FeatureFlag = "FEATURE_DISCORD_RPC";
|
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* `-DFEATURE_FILE_DROP`
|
|
|
|
* If this flag is enabled, the game will support dragging and dropping files onto it for various features.
|
|
|
|
* Disabled on MacOS.
|
2025-05-11 23:43:45 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final FEATURE_FILE_DROP:FeatureFlag = "FEATURE_FILE_DROP";
|
2025-05-11 23:43:45 +00:00
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* `-DFEATURE_FUNKVIS`
|
|
|
|
* If this flag is enabled, the game will enable the Funkin Visualizer library.
|
|
|
|
* This is used to provide audio visualization like Nene's speaker.
|
|
|
|
* Disabling this will make some waveforms inactive.
|
2025-05-11 23:43:45 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final FEATURE_FUNKVIS:FeatureFlag = "FEATURE_FUNKVIS";
|
2025-05-11 23:43:45 +00:00
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* `-DFEATURE_GHOST_TAPPING`
|
|
|
|
* If this flag is enabled, misses will not be counted when it is not the player's turn.
|
|
|
|
* Misses are still counted when the player has notes to hit.
|
2025-05-11 23:43:45 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final FEATURE_GHOST_TAPPING:FeatureFlag = "FEATURE_GHOST_TAPPING";
|
2025-05-11 23:43:45 +00:00
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* `-DFEATURE_HAPTICS`
|
|
|
|
* If this flag is enabled, the game provide haptic feedback vibrations.
|
|
|
|
* Works for mobile targets (Android and iOS).
|
2025-05-11 23:43:45 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final FEATURE_HAPTICS:FeatureFlag = "FEATURE_HAPTICS";
|
2025-05-11 23:43:45 +00:00
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* `-DFEATURE_INPUT_OFFSETS`
|
|
|
|
* If this flag is enabled, the input offsets menu will be available to configure your audio and visual offsets.
|
2025-05-11 23:43:45 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final FEATURE_INPUT_OFFSETS:FeatureFlag = "FEATURE_INPUT_OFFSETS";
|
2025-05-11 23:43:45 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* `-DFEATURE_LOG_TRACE`
|
|
|
|
* If this flag is enabled, the game will print debug traces to the console.
|
|
|
|
* Disable to improve performance a bunch.
|
|
|
|
*/
|
|
|
|
static final FEATURE_LOG_TRACE:FeatureFlag = "FEATURE_LOG_TRACE";
|
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* `-DFEATURE_MOBILE_ADVERTISEMENTS`
|
|
|
|
* If this flag is enabled, Google AdMob will be enabled.
|
|
|
|
* Banner and interstitial ads will sometimes appear.
|
2025-05-11 23:43:45 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final FEATURE_MOBILE_ADVERTISEMENTS:FeatureFlag = "FEATURE_MOBILE_ADVERTISEMENTS";
|
2025-05-11 23:43:45 +00:00
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* `-DFEATURE_MOBILE_IAP`
|
|
|
|
* If this flag is enabled, in-app purchases will be enabled.
|
|
|
|
* This includes the in-app purchase to disable mobile advertisements.
|
2025-05-11 23:43:45 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final FEATURE_MOBILE_IAP:FeatureFlag = "FEATURE_MOBILE_IAP";
|
2025-05-11 23:43:45 +00:00
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* `-DFEATURE_MOBILE_IAR`
|
|
|
|
* If this feature flag is enabled, the user may sometimes be prompted to review the app on their respective store.
|
2024-08-26 22:01:23 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final FEATURE_MOBILE_IAR:FeatureFlag = "FEATURE_MOBILE_IAR";
|
2024-08-26 22:01:23 +00:00
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* `-DFEATURE_NAUGHTYNESS`
|
|
|
|
* If this feature flag is enabled, naughtyness will be a toggleable option in the Options Menu.
|
|
|
|
* If disabled, the option will be hidden and the game will always be censored.
|
2024-08-26 22:01:23 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final FEATURE_NAUGHTYNESS:FeatureFlag = "FEATURE_NAUGHTYNESS";
|
2025-05-11 23:43:45 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* `-DFEATURE_NEWGROUNDS`
|
|
|
|
* If this flag is enabled, the game will enable the Newgrounds library.
|
|
|
|
* This is used to provide Medal and Leaderboard support.
|
|
|
|
*/
|
|
|
|
static final FEATURE_NEWGROUNDS:FeatureFlag = "FEATURE_NEWGROUNDS";
|
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* `-DFEATURE_NEWGROUNDS_AUTOLOGIN`
|
|
|
|
* If this flag is enabled, the game will attempt to automatically login to Newgrounds on startup.
|
2025-05-11 23:43:45 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final FEATURE_NEWGROUNDS_AUTOLOGIN:FeatureFlag = "FEATURE_NEWGROUNDS_AUTOLOGIN";
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* `-DFEATURE_NEWGROUNDS_DEBUG`
|
|
|
|
* If this flag is enabled, the game will enable Newgrounds.io's debug functions.
|
|
|
|
* This provides additional information in requests, as well as "faking" medal and leaderboard submissions.
|
|
|
|
*/
|
|
|
|
static final FEATURE_NEWGROUNDS_DEBUG:FeatureFlag = "FEATURE_NEWGROUNDS_DEBUG";
|
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* `-DFEATURE_NEWGROUNDS_EVENTS`
|
|
|
|
* If this flag is enabled, the game will attempt to send events to Newgrounds when the user does stuff.
|
|
|
|
* This lets us see cool anonymized stats! It only works if the user is logged in.
|
2025-05-11 23:43:45 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final FEATURE_NEWGROUNDS_EVENTS:FeatureFlag = "FEATURE_NEWGROUNDS_EVENTS";
|
2025-05-11 23:43:45 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* `-DFEATURE_NEWGROUNDS_TESTING_MEDALS`
|
|
|
|
* If this flag is enabled, use the medal IDs from the debug test bench.
|
|
|
|
* If disabled, use the actual medal IDs from the release project on Newgrounds.
|
|
|
|
*/
|
|
|
|
static final FEATURE_NEWGROUNDS_TESTING_MEDALS:FeatureFlag = "FEATURE_NEWGROUNDS_TESTING_MEDALS";
|
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* `-DFEATURE_OPEN_URL`
|
|
|
|
* If this flag is enabled, the game will support opening URLs (such as the merch page).
|
2025-05-11 23:43:45 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final FEATURE_OPEN_URL:FeatureFlag = "FEATURE_OPEN_URL";
|
2025-05-11 23:43:45 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* `-DFEATURE_PARTIAL_SOUNDS`
|
|
|
|
* If this flag is enabled, the game will enable the FlxPartialSound library.
|
|
|
|
* This is used to provide audio previews in Freeplay.
|
|
|
|
* Disabling this will make those previews not play.
|
|
|
|
*/
|
|
|
|
static final FEATURE_PARTIAL_SOUNDS:FeatureFlag = "FEATURE_PARTIAL_SOUNDS";
|
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* `-DFEATURE_POLYMOD_MODS`
|
|
|
|
* If this flag is enabled, the game will enable the Polymod library's support for atomic mod loading from the `./mods` folder.
|
|
|
|
* If this flag is disabled, no mods will be loaded.
|
2024-08-26 22:01:23 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final FEATURE_POLYMOD_MODS:FeatureFlag = "FEATURE_POLYMOD_MODS";
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2024-09-25 12:39:57 +00:00
|
|
|
/**
|
2025-05-11 23:43:45 +00:00
|
|
|
* `-DFEATURE_SCREENSHOTS`
|
2024-09-25 12:39:57 +00:00
|
|
|
* If this flag is enabled, the game will support the screenshots feature.
|
|
|
|
*/
|
|
|
|
static final FEATURE_SCREENSHOTS:FeatureFlag = "FEATURE_SCREENSHOTS";
|
|
|
|
|
2025-06-28 19:03:39 +00:00
|
|
|
/**
|
|
|
|
* `-FEATURE_DEBUG_MENU`
|
|
|
|
* If this flag is enabled, a debug menu will be accessible.
|
|
|
|
*/
|
2025-07-01 09:24:44 +00:00
|
|
|
static final FEATURE_DEBUG_MENU:FeatureFlag = "FEATURE_DEBUG_MENU";
|
2025-06-28 19:03:39 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* `-FEATURE_ANIMATION_EDITOR`
|
|
|
|
* If this flag is enabled, the Animation Editor will be accessible from the debug menu.
|
|
|
|
*/
|
2025-07-01 09:24:44 +00:00
|
|
|
static final FEATURE_ANIMATION_EDITOR:FeatureFlag = "FEATURE_ANIMATION_EDITOR";
|
2025-06-28 19:03:39 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* `-DFEATURE_CHART_EDITOR`
|
|
|
|
* If this flag is enabled, the Chart Editor will be accessible from the debug menu.
|
|
|
|
*/
|
2025-07-01 09:24:44 +00:00
|
|
|
static final FEATURE_CHART_EDITOR:FeatureFlag = "FEATURE_CHART_EDITOR";
|
2025-06-28 19:03:39 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* `-DFEATURE_STAGE_EDITOR`
|
2024-08-26 22:01:23 +00:00
|
|
|
* If this flag is enabled, the Stage Editor will be accessible from the debug menu.
|
2025-05-11 23:43:45 +00:00
|
|
|
*/
|
2024-08-26 22:01:23 +00:00
|
|
|
static final FEATURE_STAGE_EDITOR:FeatureFlag = "FEATURE_STAGE_EDITOR";
|
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
/**
|
|
|
|
* `-DFEATURE_TOUCH_CONTROLS`
|
|
|
|
* If this flag is enabled, the touch controls for the game is also enabled.
|
2025-06-16 19:34:03 +00:00
|
|
|
* Works with desktop builds I think maybe?
|
2025-06-03 06:54:53 +00:00
|
|
|
*/
|
|
|
|
static final FEATURE_TOUCH_CONTROLS:FeatureFlag = "FEATURE_TOUCH_CONTROLS";
|
|
|
|
|
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* `-DFEATURE_TOUCH_HERE_TO_PLAY`
|
|
|
|
* If this flag is enabled, the game will display a prompt to the user after the preloader completes,
|
|
|
|
* requiring them to click anywhere on the screen to start the game.
|
|
|
|
* This is done to ensure that the audio context can initialize properly on HTML5. Not necessary on desktop.
|
2024-12-17 16:12:12 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final FEATURE_TOUCH_HERE_TO_PLAY:FeatureFlag = "FEATURE_TOUCH_HERE_TO_PLAY";
|
2025-04-14 16:39:43 +00:00
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
/**
|
2025-06-16 19:34:03 +00:00
|
|
|
* `-DFEATURE_VIDEO_PLAYBACK`
|
|
|
|
* If this flag is enabled, the game will enable support for video playback.
|
|
|
|
* This requires the hxvlc library on desktop platforms.
|
2025-04-18 15:28:09 +00:00
|
|
|
*/
|
2025-06-16 19:34:03 +00:00
|
|
|
static final FEATURE_VIDEO_PLAYBACK:FeatureFlag = "FEATURE_VIDEO_PLAYBACK";
|
2025-04-17 11:22:45 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
//
|
|
|
|
// CONFIGURATION FUNCTIONS
|
|
|
|
//
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function new()
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
super();
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
envConfig = readEnvironmentFile("./.env");
|
2025-04-27 11:33:34 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
flair();
|
|
|
|
configureApp();
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
displayTarget();
|
2025-07-09 09:02:55 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
configureFeatureFlags();
|
2024-08-26 22:01:23 +00:00
|
|
|
configureCompileDefines();
|
2025-05-02 22:59:26 +00:00
|
|
|
configureIncludeMacros();
|
|
|
|
configureCustomMacros();
|
2024-08-26 22:01:23 +00:00
|
|
|
configureOutputDir();
|
|
|
|
configurePolymod();
|
|
|
|
configureHaxelibs();
|
|
|
|
configureAssets();
|
|
|
|
configureIcons();
|
2025-04-14 16:39:43 +00:00
|
|
|
|
2025-05-03 13:32:36 +00:00
|
|
|
readASTCExclusion();
|
|
|
|
|
|
|
|
if (FEATURE_COMPRESSED_TEXTURES.isEnabled(this))
|
|
|
|
{
|
|
|
|
runASTCCompressor();
|
|
|
|
}
|
|
|
|
|
2025-04-30 04:31:31 +00:00
|
|
|
if (FEATURE_MOBILE_ADVERTISEMENTS.isEnabled(this))
|
2024-12-17 16:12:12 +00:00
|
|
|
{
|
|
|
|
configureAdMobKeys();
|
|
|
|
}
|
2025-03-05 21:36:09 +00:00
|
|
|
|
2025-04-15 20:23:08 +00:00
|
|
|
if (isAndroid())
|
|
|
|
{
|
2025-07-09 09:02:55 +00:00
|
|
|
configureAndroid();
|
2025-04-15 20:23:08 +00:00
|
|
|
}
|
2025-04-12 06:56:00 +00:00
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
if (isIOS())
|
|
|
|
{
|
2025-07-09 09:02:55 +00:00
|
|
|
configureIOS();
|
2025-04-12 06:56:00 +00:00
|
|
|
}
|
2025-04-30 04:31:31 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
info("Done configuring project.");
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* Do something before building, display some ASCII or something IDK
|
|
|
|
*/
|
|
|
|
function flair()
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// TODO: Implement this.
|
|
|
|
info("Friday Night Funkin'");
|
|
|
|
info("Initializing build...");
|
|
|
|
|
|
|
|
info("Target Version: " + VERSION);
|
|
|
|
info("Git Branch: " + getGitBranch());
|
|
|
|
info("Git Commit: " + getGitCommit());
|
|
|
|
info("Git Modified? " + getGitModified());
|
2024-08-26 22:01:23 +00:00
|
|
|
info("Display? " + isDisplay());
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* Apply basic project metadata, such as the game title and version number,
|
|
|
|
* as well as info like the package name and company (used by various app stores).
|
|
|
|
*/
|
|
|
|
function configureApp()
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
this.meta.title = TITLE;
|
2025-07-10 21:00:29 +00:00
|
|
|
|
|
|
|
// ios uses this character code instead of spaces...
|
2025-07-16 18:35:24 +00:00
|
|
|
if (isIOS())
|
|
|
|
this.meta.title = ~/ /ig.replace(TITLE, "\u2002");
|
2025-07-10 21:00:29 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
this.meta.version = VERSION;
|
|
|
|
this.meta.packageName = PACKAGE_NAME;
|
|
|
|
this.meta.company = COMPANY;
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
this.app.main = MAIN_CLASS;
|
|
|
|
this.app.file = EXECUTABLE_NAME;
|
|
|
|
this.app.preloader = PRELOADER;
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
// Tell Lime where to look for the game's source code.
|
|
|
|
// If for some reason we have multiple source directories, we can add more entries here.
|
|
|
|
this.sources.push(SOURCE_DIR);
|
2024-08-26 22:01:23 +00:00
|
|
|
|
|
|
|
// Tell Lime to run some prebuild and postbuild scripts.
|
|
|
|
this.preBuildCallbacks.push(buildHaxeCLICommand(PREBUILD_HX));
|
|
|
|
this.postBuildCallbacks.push(buildHaxeCLICommand(POSTBUILD_HX));
|
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
// set the app' local languages.
|
2025-04-16 11:29:08 +00:00
|
|
|
this.languages = LANGUAGES;
|
|
|
|
|
|
|
|
// Set the build number, required for publishing the game to mobile stores.
|
|
|
|
this.meta.buildNumber = Std.string(BUILD_NUMBER);
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
// These values are only used by the SWF target I think.
|
|
|
|
// this.app.path
|
|
|
|
// this.app.init
|
|
|
|
// this.app.swfVersion
|
|
|
|
// this.app.url
|
|
|
|
|
|
|
|
// These values are only used by... FIREFOX MARKETPLACE WHAT?
|
|
|
|
// this.meta.description = "";
|
|
|
|
// this.meta.companyId = COMPANY;
|
|
|
|
// this.meta.companyUrl = COMPANY;
|
|
|
|
|
|
|
|
// Configure the window.
|
|
|
|
// Automatically configure FPS.
|
|
|
|
this.window.fps = 60;
|
|
|
|
// Set the window size.
|
|
|
|
this.window.width = 1280;
|
|
|
|
this.window.height = 720;
|
|
|
|
// Black background on release builds, magenta on debug builds.
|
|
|
|
this.window.background = FEATURE_DEBUG_FUNCTIONS.isEnabled(this) ? 0xFFFF00FF : 0xFF000000;
|
|
|
|
|
|
|
|
this.window.hardware = true;
|
|
|
|
this.window.vsync = false;
|
|
|
|
// force / allow high DPI
|
|
|
|
this.window.allowHighDPI = true;
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
if (isWeb())
|
|
|
|
{
|
|
|
|
this.window.resizable = true;
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
if (isDesktop())
|
|
|
|
{
|
|
|
|
this.window.orientation = Orientation.LANDSCAPE;
|
|
|
|
this.window.fullscreen = false;
|
|
|
|
this.window.resizable = true;
|
|
|
|
this.window.vsync = false;
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
if (isMobile())
|
|
|
|
{
|
|
|
|
this.window.orientation = Orientation.LANDSCAPE;
|
2025-06-03 06:54:53 +00:00
|
|
|
this.window.fullscreen = true;
|
2025-05-11 23:43:45 +00:00
|
|
|
this.window.resizable = false;
|
2025-06-03 06:54:53 +00:00
|
|
|
this.window.borderless = true;
|
2025-05-11 23:43:45 +00:00
|
|
|
this.window.width = 0;
|
|
|
|
this.window.height = 0;
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (isAndroid())
|
|
|
|
{
|
2025-06-03 06:54:53 +00:00
|
|
|
if (EXCLUDE_ARMV7.isEnabled(this))
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
this.excludeArchitectures.push(Architecture.ARMV7);
|
2025-06-03 06:54:53 +00:00
|
|
|
}
|
2025-05-02 22:59:26 +00:00
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
config.set("android.minimum-sdk-version", ANDROID_MINIMUM_SDK_VERSION);
|
|
|
|
config.set("android.target-sdk-version", ANDROID_TARGET_SDK_VERSION);
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* Log information about the configured target platform.
|
|
|
|
*/
|
|
|
|
function displayTarget()
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// Display the target operating system.
|
2025-05-11 23:43:45 +00:00
|
|
|
switch (this.target)
|
|
|
|
{
|
|
|
|
case Platform.WINDOWS:
|
2025-05-02 22:59:26 +00:00
|
|
|
info('Target Platform: Windows');
|
2025-05-11 23:43:45 +00:00
|
|
|
case Platform.MAC:
|
2025-05-02 22:59:26 +00:00
|
|
|
info('Target Platform: MacOS');
|
2025-05-11 23:43:45 +00:00
|
|
|
case Platform.LINUX:
|
2025-05-02 22:59:26 +00:00
|
|
|
info('Target Platform: Linux');
|
2025-05-11 23:43:45 +00:00
|
|
|
case Platform.ANDROID:
|
2025-05-02 22:59:26 +00:00
|
|
|
info('Target Platform: Android');
|
2025-05-11 23:43:45 +00:00
|
|
|
case Platform.IOS:
|
2025-05-02 22:59:26 +00:00
|
|
|
info('Target Platform: IOS');
|
2025-05-11 23:43:45 +00:00
|
|
|
case Platform.HTML5:
|
2025-05-02 22:59:26 +00:00
|
|
|
info('Target Platform: HTML5');
|
2025-05-11 23:43:45 +00:00
|
|
|
// See lime.tools.Platform for a full list.
|
|
|
|
// case Platform.EMSCRITEN: // A WebAssembly build might be interesting...
|
|
|
|
// case Platform.AIR:
|
|
|
|
// case Platform.BLACKBERRY:
|
|
|
|
// case Platform.CONSOLE_PC:
|
|
|
|
// case Platform.FIREFOX:
|
|
|
|
// case Platform.FLASH:
|
|
|
|
// case Platform.PS3:
|
|
|
|
// case Platform.PS4:
|
|
|
|
// case Platform.TIZEN:
|
|
|
|
// case Platform.TVOS:
|
|
|
|
// case Platform.VITA:
|
|
|
|
// case Platform.WEBOS:
|
|
|
|
// case Platform.WIIU:
|
|
|
|
// case Platform.XBOX1:
|
|
|
|
default:
|
2025-05-02 22:59:26 +00:00
|
|
|
error('Unsupported platform (got ${target})');
|
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
switch (this.platformType)
|
|
|
|
{
|
|
|
|
case PlatformType.DESKTOP:
|
2025-05-02 22:59:26 +00:00
|
|
|
info('Platform Type: Desktop');
|
2025-05-11 23:43:45 +00:00
|
|
|
case PlatformType.MOBILE:
|
2025-05-02 22:59:26 +00:00
|
|
|
info('Platform Type: Mobile');
|
2025-05-11 23:43:45 +00:00
|
|
|
case PlatformType.WEB:
|
2025-05-02 22:59:26 +00:00
|
|
|
info('Platform Type: Web');
|
2025-05-11 23:43:45 +00:00
|
|
|
case PlatformType.CONSOLE:
|
2025-05-02 22:59:26 +00:00
|
|
|
info('Platform Type: Console');
|
2025-05-11 23:43:45 +00:00
|
|
|
default:
|
2025-05-02 22:59:26 +00:00
|
|
|
error('Unknown platform type (got ${platformType})');
|
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
|
|
|
// Print whether we are using HXCPP, HashLink, or something else.
|
2025-05-11 23:43:45 +00:00
|
|
|
if (isWeb())
|
|
|
|
{
|
2024-08-26 22:01:23 +00:00
|
|
|
info('Target Language: JavaScript (HTML5)');
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
|
|
|
else if (isHashLink())
|
|
|
|
{
|
2024-08-26 22:01:23 +00:00
|
|
|
info('Target Language: HashLink');
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
|
|
|
else if (isNeko())
|
|
|
|
{
|
2024-08-26 22:01:23 +00:00
|
|
|
info('Target Language: Neko');
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
|
|
|
else if (isJava())
|
|
|
|
{
|
2024-08-26 22:01:23 +00:00
|
|
|
info('Target Language: Java');
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
|
|
|
else if (isNodeJS())
|
|
|
|
{
|
2024-08-26 22:01:23 +00:00
|
|
|
info('Target Language: JavaScript (NodeJS)');
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
|
|
|
else if (isCSharp())
|
|
|
|
{
|
2024-08-26 22:01:23 +00:00
|
|
|
info('Target Language: C#');
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-08-26 22:01:23 +00:00
|
|
|
info('Target Language: C++');
|
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
for (arch in this.architectures)
|
|
|
|
{
|
|
|
|
// Display the list of target architectures.
|
|
|
|
switch (arch)
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
case Architecture.X86:
|
2025-05-11 23:43:45 +00:00
|
|
|
info('Architecture: x86');
|
2025-05-02 22:59:26 +00:00
|
|
|
case Architecture.X64:
|
2025-05-11 23:43:45 +00:00
|
|
|
info('Architecture: x64');
|
2025-05-02 22:59:26 +00:00
|
|
|
case Architecture.ARMV5:
|
2025-05-11 23:43:45 +00:00
|
|
|
info('Architecture: ARMv5');
|
2025-05-02 22:59:26 +00:00
|
|
|
case Architecture.ARMV6:
|
2025-05-11 23:43:45 +00:00
|
|
|
info('Architecture: ARMv6');
|
2025-05-02 22:59:26 +00:00
|
|
|
case Architecture.ARMV7:
|
2025-05-11 23:43:45 +00:00
|
|
|
info('Architecture: ARMv7');
|
2025-05-02 22:59:26 +00:00
|
|
|
case Architecture.ARMV7S:
|
2025-05-11 23:43:45 +00:00
|
|
|
info('Architecture: ARMv7S');
|
2025-05-02 22:59:26 +00:00
|
|
|
case Architecture.ARM64:
|
2025-05-11 23:43:45 +00:00
|
|
|
info('Architecture: ARMx64');
|
2025-05-02 22:59:26 +00:00
|
|
|
case Architecture.MIPS:
|
2025-05-11 23:43:45 +00:00
|
|
|
info('Architecture: MIPS');
|
2025-05-02 22:59:26 +00:00
|
|
|
case Architecture.MIPSEL:
|
2025-05-11 23:43:45 +00:00
|
|
|
info('Architecture: MIPSEL');
|
2025-05-02 22:59:26 +00:00
|
|
|
case null:
|
2025-05-11 23:43:45 +00:00
|
|
|
if (!isWeb())
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
error('Unsupported architecture (got null on non-web platform)');
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
info('Architecture: Web');
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2025-05-02 22:59:26 +00:00
|
|
|
default:
|
2025-05-11 23:43:45 +00:00
|
|
|
error('Unsupported architecture (got ${arch})');
|
|
|
|
}
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* Apply various feature flags based on the target platform and the user-provided build flags.
|
|
|
|
*/
|
|
|
|
function configureFeatureFlags()
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// You can explicitly override any of these.
|
|
|
|
// For example, `-DGITHUB_BUILD` or `-DNO_HARDCODED_CREDITS`
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-06-16 19:34:03 +00:00
|
|
|
//
|
|
|
|
// BUILD FLAGS
|
|
|
|
//
|
|
|
|
|
2025-04-16 11:29:08 +00:00
|
|
|
// Should be false unless explicitly requested.
|
|
|
|
GITHUB_BUILD.apply(this, false);
|
|
|
|
EXCLUDE_ARMV7.apply(this, false);
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
// Should be true unless explicitly requested.
|
|
|
|
HARDCODED_CREDITS.apply(this, true);
|
2025-06-22 20:45:10 +00:00
|
|
|
UNLOCK_EVERYTHING.apply(this, true);
|
2025-06-16 19:34:03 +00:00
|
|
|
|
|
|
|
// Should be true only on web builds.
|
|
|
|
// Enabling embedding and preloading is required to preload assets properly.
|
|
|
|
EMBED_ASSETS.apply(this, isWeb());
|
|
|
|
PRELOAD_ALL.apply(this, !isWeb());
|
|
|
|
|
|
|
|
// Should default to true on workspace builds and false on release builds.
|
|
|
|
REDIRECT_ASSETS_FOLDER.apply(this, isDebug() && isDesktop());
|
|
|
|
|
|
|
|
// Should be true only on debug mobile builds.
|
|
|
|
TESTING_ADS.apply(this, isDebug() && FEATURE_MOBILE_ADVERTISEMENTS.isEnabled(this));
|
|
|
|
|
|
|
|
// Should be true on mobile builds.
|
|
|
|
CENSOR_EXPLETIVES.apply(this, isMobile());
|
|
|
|
|
|
|
|
//
|
|
|
|
// FEATURE FLAGS
|
|
|
|
//
|
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
FEATURE_FUNKVIS.apply(this, true);
|
2025-07-17 00:32:26 +00:00
|
|
|
FEATURE_LOG_TRACE.apply(this, true);
|
2025-06-16 19:34:03 +00:00
|
|
|
FEATURE_NAUGHTYNESS.apply(this, true);
|
|
|
|
FEATURE_OPEN_URL.apply(this, true);
|
2025-05-02 22:59:26 +00:00
|
|
|
FEATURE_PARTIAL_SOUNDS.apply(this, true);
|
2025-06-16 19:34:03 +00:00
|
|
|
FEATURE_POLYMOD_MODS.apply(this, true);
|
2025-06-03 09:55:35 +00:00
|
|
|
|
|
|
|
// Video playback should be enabled on desktop, web, and mobile.
|
|
|
|
// HXCPP has trouble with iOS simulator builds though...
|
|
|
|
FEATURE_VIDEO_PLAYBACK.apply(this, !isIOSSimulator());
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
// Should be true on debug builds or if GITHUB_BUILD is enabled.
|
|
|
|
FEATURE_DEBUG_FUNCTIONS.apply(this, isDebug() || GITHUB_BUILD.isEnabled(this));
|
|
|
|
FEATURE_RESULTS_DEBUG.apply(this, isDebug() || GITHUB_BUILD.isEnabled(this));
|
2024-10-18 20:00:06 +00:00
|
|
|
|
2025-06-16 19:34:03 +00:00
|
|
|
// Should be true on desktop, non-tester builds.
|
|
|
|
// We don't want testers to accidentally leak songs to their Discord friends!
|
|
|
|
FEATURE_DISCORD_RPC.apply(this, isDesktop() && !FEATURE_DEBUG_FUNCTIONS.isEnabled(this));
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-06-16 19:34:03 +00:00
|
|
|
// Newgrounds features
|
2025-06-04 16:43:49 +00:00
|
|
|
FEATURE_NEWGROUNDS.apply(this, !isMobile());
|
2025-05-02 22:59:26 +00:00
|
|
|
FEATURE_NEWGROUNDS_DEBUG.apply(this, false);
|
|
|
|
FEATURE_NEWGROUNDS_TESTING_MEDALS.apply(this, FEATURE_NEWGROUNDS.isEnabled(this) && FEATURE_DEBUG_FUNCTIONS.isEnabled(this));
|
|
|
|
FEATURE_NEWGROUNDS_AUTOLOGIN.apply(this, FEATURE_NEWGROUNDS.isEnabled(this) && isWeb());
|
|
|
|
FEATURE_NEWGROUNDS_EVENTS.apply(this, FEATURE_NEWGROUNDS.isEnabled(this));
|
2024-10-07 03:51:50 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
// Should be true except on web and mobile builds.
|
2025-06-16 19:34:03 +00:00
|
|
|
// Debug editors aren't built to work on web or mobile right now.
|
2025-06-28 19:03:39 +00:00
|
|
|
FEATURE_DEBUG_MENU.apply(this, !(isWeb() || isMobile()));
|
|
|
|
FEATURE_ANIMATION_EDITOR.apply(this, !(isWeb() || isMobile()));
|
2025-05-02 22:59:26 +00:00
|
|
|
FEATURE_CHART_EDITOR.apply(this, !(isWeb() || isMobile()));
|
2025-05-28 23:19:08 +00:00
|
|
|
FEATURE_STAGE_EDITOR.apply(this, !(isWeb() || isMobile()));
|
2024-09-25 12:39:57 +00:00
|
|
|
|
2025-06-30 10:59:50 +00:00
|
|
|
// Should be true except on web builds (some asset stuff breaks it)
|
|
|
|
FEATURE_INPUT_OFFSETS.apply(this, !isWeb());
|
2025-06-22 20:45:10 +00:00
|
|
|
|
2025-04-09 06:34:31 +00:00
|
|
|
// Should be true except on web and mobile builds.
|
2025-06-16 19:34:03 +00:00
|
|
|
// Screenshots doesn't work there, and mobile has its own screenshots anyway.
|
2025-04-09 06:34:31 +00:00
|
|
|
FEATURE_SCREENSHOTS.apply(this, !(isWeb() || isMobile()));
|
2025-04-14 17:32:31 +00:00
|
|
|
|
2025-06-22 20:45:10 +00:00
|
|
|
// Should be true except on MacOS and mobile builds.
|
2025-06-16 19:34:03 +00:00
|
|
|
// Dragging and dropping files onto the window doesn't work there.
|
|
|
|
FEATURE_FILE_DROP.apply(this, !(isMac() || isMobile()));
|
|
|
|
|
2025-06-22 20:45:10 +00:00
|
|
|
// Audio context issues only exist on web builds.
|
2025-06-16 19:34:03 +00:00
|
|
|
FEATURE_TOUCH_HERE_TO_PLAY.apply(this, isWeb());
|
2025-04-27 11:33:34 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
// Should be true only on mobile builds.
|
2025-06-16 19:34:03 +00:00
|
|
|
FEATURE_HAPTICS.apply(this, isMobile());
|
2025-05-02 22:59:26 +00:00
|
|
|
FEATURE_TOUCH_CONTROLS.apply(this, isMobile());
|
2025-04-14 17:32:31 +00:00
|
|
|
|
2025-05-01 23:55:44 +00:00
|
|
|
// Should be true only on mobile release builds. Remember you can add the flag manually for testing.
|
2025-05-02 22:59:26 +00:00
|
|
|
FEATURE_MOBILE_ADVERTISEMENTS.apply(this, (isMobile() && isRelease() && envConfig != null));
|
2025-05-05 21:03:22 +00:00
|
|
|
FEATURE_MOBILE_IAP.apply(this, (isMobile() && isRelease() && envConfig != null));
|
2025-06-04 00:00:34 +00:00
|
|
|
FEATURE_MOBILE_IAR.apply(this, (isMobile() && isRelease()));
|
2025-04-18 15:28:09 +00:00
|
|
|
|
2025-06-16 19:34:03 +00:00
|
|
|
// The coveted ghost tapping feature.
|
|
|
|
// Essential on mobile but delayed on desktop.
|
|
|
|
// Please send targeted harassment to PhantomArcade about this.
|
|
|
|
FEATURE_GHOST_TAPPING.apply(this, isMobile());
|
2025-06-26 21:54:03 +00:00
|
|
|
|
|
|
|
// Enable ASTC Compressed textures for mobile.
|
|
|
|
// Since mobile is pretty memory safe (I'm looking at you Apple...) we need them BADLY to have the game run properly.
|
|
|
|
// It's kept off for desktop due to the low ASTC support on desktop GPUs (which seem to be only among Intergrated Graphics).
|
|
|
|
FEATURE_COMPRESSED_TEXTURES.apply(this, isMobile() && isRelease());
|
2025-01-28 18:29:15 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set compilation flags which are not feature flags.
|
|
|
|
*/
|
2025-05-11 23:43:45 +00:00
|
|
|
function configureCompileDefines()
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// Enable OpenFL's error handler. Required for the crash logger.
|
2024-08-26 22:01:23 +00:00
|
|
|
setHaxedef("openfl-enable-handle-error");
|
|
|
|
|
2025-06-04 13:31:15 +00:00
|
|
|
// Disable a macro in Lime that generates a random number for Assets.cache.version every build.
|
|
|
|
// This doesn't seem to be of any use and it causes lime.utils.AssetCache to be re-compiled on every build.
|
2025-06-05 01:03:31 +00:00
|
|
|
setHaxedef("lime_disable_assets_version");
|
2025-06-04 13:31:15 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
// Enable stack trace tracking. Good for debugging but has a (minor) performance impact.
|
|
|
|
setHaxedef("HXCPP_CHECK_POINTER");
|
|
|
|
setHaxedef("HXCPP_STACK_LINE");
|
|
|
|
setHaxedef("HXCPP_STACK_TRACE");
|
|
|
|
setHaxedef("hscriptPos");
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
setHaxedef("safeMode");
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
// If we aren't using the Flixel debugger, strip it out.
|
2025-05-11 23:43:45 +00:00
|
|
|
if (FEATURE_DEBUG_FUNCTIONS.isDisabled(this))
|
|
|
|
{
|
|
|
|
setHaxedef("FLX_NO_DEBUG");
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-07-09 11:36:12 +00:00
|
|
|
if (FEATURE_LOG_TRACE.isDisabled(this))
|
|
|
|
{
|
2025-07-15 09:40:25 +00:00
|
|
|
addHaxeFlag("--no-traces");
|
2025-07-09 11:36:12 +00:00
|
|
|
}
|
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
// Disable the built in pause screen when unfocusing the game.
|
|
|
|
setHaxedef("FLX_NO_FOCUS_LOST_SCREEN");
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
// HaxeUI configuration.
|
|
|
|
setHaxedef("haxeui_no_mouse_reset");
|
|
|
|
setHaxedef("haxeui_focus_out_on_click"); // Unfocus a dialog when clicking out of it
|
|
|
|
setHaxedef("haxeui_dont_impose_base_class"); // Suppress a macro error
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
if (isRelease())
|
|
|
|
{
|
|
|
|
// Improve performance on Nape
|
|
|
|
// TODO: Do we even use Nape?
|
|
|
|
setHaxedef("NAPE_RELEASE_BUILD");
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
// Cleaner looking compiler errors.
|
|
|
|
setHaxedef("message.reporting", "pretty");
|
2024-09-18 00:50:09 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
if (FEATURE_DEBUG_TRACY.isEnabled(this))
|
|
|
|
{
|
|
|
|
setHaxedef("HXCPP_TELEMETRY"); // Enable telemetry
|
|
|
|
setHaxedef("HXCPP_TRACY"); // Enable Tracy telemetry
|
|
|
|
setHaxedef("HXCPP_TRACY_MEMORY"); // Track memory allocations
|
|
|
|
setHaxedef("HXCPP_TRACY_ON_DEMAND"); // Only collect telemetry when Tracy is open and reachable
|
|
|
|
// setHaxedef("HXCPP_TRACY_INCLUDE_CALLSTACKS"); // Inspect callstacks per zone, inflating telemetry data
|
2024-09-18 00:50:09 +00:00
|
|
|
|
2025-03-04 15:25:41 +00:00
|
|
|
setHaxedef("absolute-paths"); // Fix source locations so Tracy can see them
|
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* Set compilation flags which manage dead code elimination.
|
|
|
|
*/
|
|
|
|
function configureIncludeMacros()
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// Disable dead code elimination.
|
|
|
|
// This prevents functions that are unused by the base game from being unavailable to HScript.
|
|
|
|
addHaxeFlag("-dce no");
|
|
|
|
|
|
|
|
// Forcibly include all Funkin' classes in builds.
|
|
|
|
// This prevents classes that are unused by the base game from being unavailable to HScript.
|
|
|
|
addHaxeMacro("include('funkin', true, ['funkin.mobile.*'])");
|
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
if (isMobile())
|
|
|
|
{
|
|
|
|
addHaxeMacro("include('funkin.mobile')");
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure all HaxeUI components are available at runtime.
|
|
|
|
addHaxeMacro("include('haxe.ui.backend.flixel.components')");
|
|
|
|
addHaxeMacro("include('haxe.ui.core')");
|
|
|
|
addHaxeMacro("include('haxe.ui.components')");
|
|
|
|
addHaxeMacro("include('haxe.ui.containers')");
|
|
|
|
addHaxeMacro("include('haxe.ui.containers.dialogs')");
|
|
|
|
addHaxeMacro("include('haxe.ui.containers.menus')");
|
|
|
|
addHaxeMacro("include('haxe.ui.containers.properties')");
|
|
|
|
|
|
|
|
// Ensure all Flixel classes are available at runtime.
|
|
|
|
// Explicitly ignore packages which require additional dependencies.
|
|
|
|
addHaxeMacro("include('flixel', true, [ 'flixel.addons.editors.spine.*', 'flixel.addons.nape.*', 'flixel.system.macros.*', 'flixel.addons.tile.FlxRayCastTilemap' ])");
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* Set compilation flags which manage bespoke build-time macros.
|
|
|
|
*/
|
|
|
|
function configureCustomMacros()
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// This macro allows addition of new functionality to existing Flixel. -->
|
|
|
|
addHaxeMacro("addMetadata('@:build(funkin.util.macro.FlxMacro.buildFlxBasic())', 'flixel.FlxBasic')");
|
2024-08-26 22:01:23 +00:00
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
function configureOutputDir()
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// Set the output directory. Depends on the target platform and build type.
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
var buildDir = 'export/${isDebug() ? 'debug' : 'release'}';
|
2024-12-02 20:36:26 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
// we use a dedicated 'tracy' folder, since it generally needs a recompile when in use
|
2025-05-11 23:43:45 +00:00
|
|
|
if (FEATURE_DEBUG_TRACY.isEnabled(this)) buildDir += "-tracy";
|
2024-12-02 20:36:26 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
// trailing slash might not be needed, works fine on macOS without it, but I haven't tested on Windows!
|
|
|
|
buildDir += "/";
|
2024-12-02 20:36:26 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
info('Output directory: $buildDir');
|
|
|
|
// setenv('BUILD_DIR', buildDir);
|
|
|
|
app.path = buildDir;
|
2024-08-26 22:01:23 +00:00
|
|
|
}
|
|
|
|
|
2025-07-09 09:02:55 +00:00
|
|
|
function configureAndroid()
|
2025-06-03 06:54:53 +00:00
|
|
|
{
|
2025-07-09 09:02:55 +00:00
|
|
|
javaPaths.push(Path.join([SOURCE_DIR, 'funkin/mobile/external/android/java']));
|
|
|
|
|
|
|
|
if (isRelease())
|
2025-06-03 06:54:53 +00:00
|
|
|
{
|
2025-07-09 09:02:55 +00:00
|
|
|
if (envConfig != null)
|
|
|
|
{
|
|
|
|
keystore = new Keystore();
|
|
|
|
keystore.path = Std.string(envConfig.get('ANDROID_KEYSTORE_PATH'));
|
|
|
|
keystore.alias = Std.string(envConfig.get('ANDROID_KEYSTORE_ALIAS'));
|
|
|
|
keystore.password = Std.string(envConfig.get('ANDROID_KEYSTORE_PASSWORD'));
|
|
|
|
}
|
2025-04-30 04:31:31 +00:00
|
|
|
|
2025-07-09 09:02:55 +00:00
|
|
|
Reflect.setField(config.get('android.manifest'), 'xmlns:tools', 'http://schemas.android.com/tools');
|
2025-04-30 04:31:31 +00:00
|
|
|
|
2025-07-09 09:02:55 +00:00
|
|
|
final permissionsConfig:Array<String> = [
|
|
|
|
'<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" />',
|
|
|
|
'<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="remove" />'
|
|
|
|
];
|
|
|
|
|
|
|
|
final xmlChildren:Null<Array<String>> = config.get('android.manifest').xmlChildren;
|
|
|
|
|
|
|
|
if (xmlChildren != null)
|
|
|
|
{
|
|
|
|
config.get('android.manifest').xmlChildren = xmlChildren.concat(permissionsConfig);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
config.get('android.manifest').xmlChildren = permissionsConfig;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isBundle())
|
|
|
|
{
|
|
|
|
config.set("android.gradle-project-directory", "bin-bundle");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
final modsFolderProvider = [
|
|
|
|
'<provider android:authorities="$PACKAGE_NAME.docprovider" android:name="funkin.provider.DataFolderProvider" android:grantUriPermissions="true" android:exported="true" android:permission="android.permission.MANAGE_DOCUMENTS">',
|
|
|
|
' <intent-filter>',
|
|
|
|
' <action android:name="android.content.action.DOCUMENTS_PROVIDER" />',
|
|
|
|
' </intent-filter>',
|
|
|
|
'</provider>'
|
2025-06-03 06:54:53 +00:00
|
|
|
];
|
2025-04-30 04:31:31 +00:00
|
|
|
|
2025-07-09 09:02:55 +00:00
|
|
|
final xmlChildren:Null<Array<String>> = config.get('android.application').xmlChildren;
|
2025-04-30 04:31:31 +00:00
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
if (xmlChildren != null)
|
|
|
|
{
|
2025-07-09 09:02:55 +00:00
|
|
|
config.get('android.application').xmlChildren = xmlChildren.concat(modsFolderProvider);
|
2025-06-03 06:54:53 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2025-07-09 09:02:55 +00:00
|
|
|
config.get('android.application').xmlChildren = modsFolderProvider;
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2025-07-10 13:26:01 +00:00
|
|
|
|
|
|
|
final extensions:Null<Array<String>> = config.getArrayString('android.extension');
|
|
|
|
|
|
|
|
for (extension in ANDROID_EXTENSIONS)
|
|
|
|
{
|
|
|
|
if (extensions == null || extensions != null && extensions.indexOf(extension) == -1)
|
|
|
|
{
|
|
|
|
config.push("android.extension", extension);
|
|
|
|
}
|
|
|
|
}
|
2025-07-09 09:02:55 +00:00
|
|
|
}
|
2025-04-30 04:31:31 +00:00
|
|
|
|
2025-07-09 09:02:55 +00:00
|
|
|
function configureIOS()
|
|
|
|
{
|
|
|
|
config.set("ios.non-exempt-encryption", "false");
|
|
|
|
config.set("ios.team-id", IOS_TEAM_ID);
|
|
|
|
config.set("ios.deployment", "16.0");
|
|
|
|
|
|
|
|
// launchStoryboard = new LaunchStoryboard();
|
|
|
|
// launchStoryboard.path = "./LaunchScreen.storyboard";
|
2025-06-03 06:54:53 +00:00
|
|
|
}
|
2025-04-30 04:31:31 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
function configurePolymod()
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// The file extension to use for script files.
|
|
|
|
setHaxedef("POLYMOD_SCRIPT_EXT", ".hscript");
|
|
|
|
// Which asset library to use for scripts.
|
|
|
|
setHaxedef("POLYMOD_SCRIPT_LIBRARY", "scripts");
|
|
|
|
// The base path from which scripts should be accessed.
|
|
|
|
setHaxedef("POLYMOD_ROOT_PATH", "scripts/");
|
|
|
|
// Determines the subdirectory of the mod folder used for file appending.
|
|
|
|
setHaxedef("POLYMOD_APPEND_FOLDER", "_append");
|
|
|
|
// Determines the subdirectory of the mod folder used for file merges.
|
|
|
|
setHaxedef("POLYMOD_MERGE_FOLDER", "_merge");
|
|
|
|
// Determines the file in the mod folder used for metadata.
|
|
|
|
setHaxedef("POLYMOD_MOD_METADATA_FILE", "_polymod_meta.json");
|
|
|
|
// Determines the file in the mod folder used for the icon.
|
|
|
|
setHaxedef("POLYMOD_MOD_ICON_FILE", "_polymod_icon.png");
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
if (isDebug())
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// Turns on additional debug logging.
|
2024-08-26 22:01:23 +00:00
|
|
|
setHaxedef("POLYMOD_DEBUG");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
function configureHaxelibs()
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// Don't enforce
|
2025-04-14 15:20:15 +00:00
|
|
|
// addHaxelib('lime'); // Game engine backend
|
|
|
|
// addHaxelib('openfl'); // Game engine backend
|
2024-08-26 22:01:23 +00:00
|
|
|
|
|
|
|
addHaxelib('flixel'); // Game engine
|
|
|
|
|
|
|
|
addHaxelib('flixel-addons'); // Additional utilities for Flixel
|
|
|
|
addHaxelib('hscript'); // Scripting
|
|
|
|
// addHaxelib('flixel-ui'); // UI framework (DEPRECATED)
|
|
|
|
addHaxelib('haxeui-core'); // UI framework
|
|
|
|
addHaxelib('haxeui-flixel'); // Integrate HaxeUI with Flixel
|
|
|
|
|
|
|
|
addHaxelib('polymod'); // Modding framework
|
|
|
|
addHaxelib('flxanimate'); // Texture atlas rendering
|
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
addHaxelib('json2object'); // JSON parsing
|
2024-08-26 22:01:23 +00:00
|
|
|
addHaxelib('jsonpath'); // JSON parsing
|
|
|
|
addHaxelib('jsonpatch'); // JSON parsing
|
2025-05-02 22:59:26 +00:00
|
|
|
addHaxelib('thx.core'); // General utility library, "the lodash of Haxe"
|
|
|
|
addHaxelib('thx.semver'); // Version string handling
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
if (isDebug())
|
|
|
|
{
|
|
|
|
addHaxelib('hxcpp-debug-server'); // VSCode debug support
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
if (isDesktop() || isMobile() && !isHashLink() && FEATURE_VIDEO_PLAYBACK.isEnabled(this))
|
2025-05-11 23:43:45 +00:00
|
|
|
{
|
2024-12-17 14:43:16 +00:00
|
|
|
// hxvlc doesn't function on HashLink or non-desktop platforms
|
2025-05-11 23:43:45 +00:00
|
|
|
// It's also unnecessary if video playback is disabled
|
2024-12-17 14:43:16 +00:00
|
|
|
addHaxelib('hxvlc'); // Video playback
|
2024-08-26 22:01:23 +00:00
|
|
|
}
|
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
if (isAndroid())
|
|
|
|
{
|
2025-04-18 15:28:09 +00:00
|
|
|
addHaxelib('extension-androidtools'); // Android Functions
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2025-04-14 15:20:15 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
if (FEATURE_DISCORD_RPC.isEnabled(this))
|
|
|
|
{
|
|
|
|
addHaxelib('hxdiscord_rpc'); // Discord API
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
if (FEATURE_NEWGROUNDS.isEnabled(this))
|
|
|
|
{
|
|
|
|
addHaxelib('newgrounds'); // Newgrounds API
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
if (FEATURE_FUNKVIS.isEnabled(this))
|
|
|
|
{
|
|
|
|
addHaxelib('funkin.vis'); // Audio visualization
|
2024-08-26 22:01:23 +00:00
|
|
|
addHaxelib('grig.audio'); // Audio data utilities
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
if (FEATURE_PARTIAL_SOUNDS.isEnabled(this))
|
|
|
|
{
|
2025-01-12 09:07:49 +00:00
|
|
|
addHaxelib('FlxPartialSound'); // Partial sound
|
|
|
|
}
|
2025-04-14 16:39:43 +00:00
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
if (FEATURE_MOBILE_ADVERTISEMENTS.isEnabled(this))
|
|
|
|
{
|
2024-12-17 16:12:12 +00:00
|
|
|
addHaxelib('extension-admob'); // Ads Extension
|
|
|
|
}
|
2025-01-13 20:13:41 +00:00
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
if (FEATURE_HAPTICS.isEnabled(this))
|
|
|
|
{
|
|
|
|
addHaxelib('extension-haptics'); // Haptic feedback
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2025-04-17 11:51:33 +00:00
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
if (FEATURE_MOBILE_IAP.isEnabled(this))
|
|
|
|
{
|
|
|
|
addHaxelib('extension-iapcore'); // In-app purchases Extension
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2025-06-04 00:00:34 +00:00
|
|
|
|
|
|
|
if (FEATURE_MOBILE_IAR.isEnabled(this))
|
|
|
|
{
|
|
|
|
addHaxelib('extension-iarcore'); // In-app reviews Extension
|
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
function configureAssets()
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
var exclude = EXCLUDE_ASSETS.concat(isWeb() ? EXCLUDE_ASSETS_WEB : EXCLUDE_ASSETS_NATIVE);
|
|
|
|
var shouldPreload = PRELOAD_ALL.isEnabled(this);
|
|
|
|
var shouldEmbed = EMBED_ASSETS.isEnabled(this);
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-06-14 03:00:33 +00:00
|
|
|
if (CENSOR_EXPLETIVES.isEnabled(this))
|
|
|
|
{
|
|
|
|
exclude = exclude.concat(EXCLUDE_ASSETS_CENSORED);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
exclude = exclude.concat(EXCLUDE_ASSETS_UNCENSORED);
|
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
if (shouldEmbed)
|
|
|
|
{
|
|
|
|
info('Embedding assets into executable...');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
info('Including assets alongside executable...');
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-04-16 11:29:08 +00:00
|
|
|
// Default asset library
|
|
|
|
var shouldPreloadDefault = true;
|
|
|
|
addAssetLibrary("default", shouldEmbed, shouldPreloadDefault);
|
|
|
|
addAssetPath("assets/preload", "assets", "default", ["*"], exclude, shouldEmbed, "assets");
|
|
|
|
|
|
|
|
// Font assets
|
|
|
|
var shouldEmbedFonts = true;
|
|
|
|
addAssetPath("assets/fonts", null, "default", ["*"], exclude, shouldEmbedFonts, "assets");
|
|
|
|
|
|
|
|
// Shared asset libraries
|
|
|
|
addAssetLibrary("songs", shouldEmbed, shouldPreload);
|
|
|
|
addAssetPath("assets/songs", "assets/songs", "songs", ["*"], exclude, shouldEmbed, "assets");
|
|
|
|
addAssetLibrary("shared", shouldEmbed, shouldPreload);
|
|
|
|
addAssetPath("assets/shared", "assets/shared", "shared", ["*"], exclude, shouldEmbed, "assets");
|
|
|
|
if (FEATURE_VIDEO_PLAYBACK.isEnabled(this))
|
|
|
|
{
|
|
|
|
var shouldEmbedVideos = false;
|
|
|
|
addAssetLibrary("videos", shouldEmbedVideos, shouldPreload);
|
|
|
|
addAssetPath("assets/videos", "assets/videos", "videos", ["*"], exclude, shouldEmbedVideos, "assets");
|
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-04-16 11:29:08 +00:00
|
|
|
// Level asset libraries
|
|
|
|
addAssetLibrary("tutorial", shouldEmbed, shouldPreload);
|
|
|
|
addAssetPath("assets/tutorial", "assets/tutorial", "tutorial", ["*"], exclude, shouldEmbed, "assets");
|
|
|
|
addAssetLibrary("week1", shouldEmbed, shouldPreload);
|
2025-05-02 22:59:26 +00:00
|
|
|
addAssetPath("assets/week1", "assets/week1", "week1", ["*"], exclude, shouldEmbed, "assets");
|
2025-04-16 11:29:08 +00:00
|
|
|
addAssetLibrary("week2", shouldEmbed, shouldPreload);
|
|
|
|
addAssetPath("assets/week2", "assets/week2", "week2", ["*"], exclude, shouldEmbed, "assets");
|
|
|
|
addAssetLibrary("week3", shouldEmbed, shouldPreload);
|
|
|
|
addAssetPath("assets/week3", "assets/week3", "week3", ["*"], exclude, shouldEmbed, "assets");
|
|
|
|
addAssetLibrary("week4", shouldEmbed, shouldPreload);
|
|
|
|
addAssetPath("assets/week4", "assets/week4", "week4", ["*"], exclude, shouldEmbed, "assets");
|
|
|
|
addAssetLibrary("week5", shouldEmbed, shouldPreload);
|
|
|
|
addAssetPath("assets/week5", "assets/week5", "week5", ["*"], exclude, shouldEmbed, "assets");
|
|
|
|
addAssetLibrary("week6", shouldEmbed, shouldPreload);
|
|
|
|
addAssetPath("assets/week6", "assets/week6", "week6", ["*"], exclude, shouldEmbed, "assets");
|
|
|
|
addAssetLibrary("week7", shouldEmbed, shouldPreload);
|
|
|
|
addAssetPath("assets/week7", "assets/week7", "week7", ["*"], exclude, shouldEmbed, "assets");
|
|
|
|
addAssetLibrary("weekend1", shouldEmbed, shouldPreload);
|
|
|
|
addAssetPath("assets/weekend1", "assets/weekend1", "weekend1", ["*"], exclude, shouldEmbed, "assets");
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-06-30 17:14:29 +00:00
|
|
|
// Art asset library (where README and CHANGELOG pull from)
|
2025-05-02 22:59:26 +00:00
|
|
|
var shouldEmbedArt = false;
|
|
|
|
var shouldPreloadArt = false;
|
|
|
|
addAssetLibrary("art", shouldEmbedArt, shouldPreloadArt);
|
|
|
|
addAsset("art/readme.txt", "do NOT readme.txt", "art", shouldEmbedArt);
|
|
|
|
addAsset("LICENSE.md", "LICENSE.md", "art", shouldEmbedArt);
|
2025-06-30 17:14:29 +00:00
|
|
|
addAsset("CHANGELOG.md", "CHANGELOG.md", "art", shouldEmbedArt);
|
2025-04-30 04:31:31 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
info('Done configuring assets.');
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Configure the application's favicon and executable icon.
|
|
|
|
*/
|
2025-03-05 21:36:09 +00:00
|
|
|
function configureIcons()
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
info('Configuring application icons...');
|
2025-07-02 16:01:32 +00:00
|
|
|
|
|
|
|
if (isAndroid())
|
2025-06-03 06:54:53 +00:00
|
|
|
{
|
2025-07-02 16:01:32 +00:00
|
|
|
// Adaptive icons
|
|
|
|
// TODO: Add Adapative Icons in Lime
|
|
|
|
templatePaths.push("templates");
|
|
|
|
|
|
|
|
var androidTheme:String = "@style/LimeAppMainTheme";
|
|
|
|
if (window.fullscreen != null && window.fullscreen)
|
|
|
|
{
|
|
|
|
androidTheme += "Fullscreen";
|
|
|
|
}
|
|
|
|
|
2025-07-16 18:35:24 +00:00
|
|
|
final iconXmlChild:Dynamic = {
|
|
|
|
"android:label": meta.title,
|
|
|
|
"android:allowBackup": "true",
|
|
|
|
"android:theme": androidTheme,
|
|
|
|
"android:hardwareAccelerated": "true",
|
|
|
|
"android:allowNativeHeapPointerTagging": ANDROID_TARGET_SDK_VERSION >= 30 ? "false" : null,
|
|
|
|
"android:largeHeap": "true",
|
|
|
|
"android:icon": "@mipmap/ic_launcher",
|
|
|
|
"android:roundIcon": "@mipmap/ic_launcher_round"
|
2025-07-02 16:01:32 +00:00
|
|
|
};
|
|
|
|
|
2025-07-16 18:35:24 +00:00
|
|
|
config.set('android.application', iconXmlChild);
|
2025-06-03 06:54:53 +00:00
|
|
|
}
|
2025-07-02 16:01:32 +00:00
|
|
|
else if (isIOS())
|
2025-06-03 06:54:53 +00:00
|
|
|
{
|
2025-06-12 08:23:37 +00:00
|
|
|
// Note: the icons on iOS (and likely even android too) support nice P3 colors space
|
|
|
|
// However, lime's IconHelper.hx` and the general accompyaning encoding stuff to automatically
|
|
|
|
// generate icons of different sizes doesnt accomodate for the nice yummy color space
|
|
|
|
// so we do indeed need to make sure we declare the icons here
|
|
|
|
// on iOS
|
|
|
|
|
|
|
|
// addIcon("icon16_noalpha.png", 16);
|
|
|
|
// addIcon("art/icons/icon32_noalpha.png", 32);
|
|
|
|
// addIcon("art/icons/icon64_noalpha.png", 64);
|
|
|
|
// addIcon("art/icons/iconOG_noalpha.png");
|
|
|
|
addIcon("art/icons/bf-iOS-Default-20x20@2x.png", 40);
|
|
|
|
addIcon("art/icons/bf-iOS-Default-20x20@3x.png", 60);
|
|
|
|
addIcon("art/icons/bf-iOS-Default-29x29.png", 29);
|
|
|
|
addIcon("art/icons/bf-iOS-Default-29x29@2x.png", 58);
|
|
|
|
addIcon("art/icons/bf-iOS-Default-29x29@3x.png", 87);
|
|
|
|
addIcon("art/icons/bf-iOS-Default-40x40@2x.png", 80);
|
|
|
|
addIcon("art/icons/bf-iOS-Default-60x60@2x.png", 120);
|
|
|
|
addIcon("art/icons/bf-iOS-Default-60x60@3x.png", 180);
|
|
|
|
addIcon("art/icons/bf-iOS-Default-1024x1024.png", 1024);
|
|
|
|
addIcon("art/icons/bf-iOS-Default-1024x1024.png");
|
2025-03-05 21:36:09 +00:00
|
|
|
}
|
2025-07-02 16:01:32 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
addIcon("art/icons/icon16.png", 16);
|
|
|
|
addIcon("art/icons/icon32.png", 32);
|
|
|
|
addIcon("art/icons/icon64.png", 64);
|
|
|
|
addIcon("art/icons/iconOG.png");
|
|
|
|
|
|
|
|
info('Done configuring icons.');
|
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
}
|
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
/**
|
|
|
|
* Configure the platforms' Ad Mob application keys.
|
|
|
|
*/
|
|
|
|
function configureAdMobKeys()
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
if (envConfig == null) return;
|
2025-04-17 11:22:45 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
if (isAndroid())
|
|
|
|
{
|
2025-06-03 06:54:53 +00:00
|
|
|
setenv("ADMOB_APPID", Std.string(envConfig.get('ANDROID_ADMOB_APP_ID')));
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2025-04-14 16:39:43 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
if (isIOS())
|
|
|
|
{
|
2025-06-03 06:54:53 +00:00
|
|
|
setenv("ADMOB_APPID", Std.string(envConfig.get('IOS_ADMOB_APP_ID')));
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
}
|
2025-04-14 16:39:43 +00:00
|
|
|
|
2025-07-16 18:35:28 +00:00
|
|
|
//
|
|
|
|
// HELPER FUNCTIONS
|
|
|
|
// Easy functions to make the code more readable.
|
|
|
|
//
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function isWeb():Bool
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
return this.platformType == PlatformType.WEB;
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function isMobile():Bool
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
return this.platformType == PlatformType.MOBILE;
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function isDesktop():Bool
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
return this.platformType == PlatformType.DESKTOP;
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function isConsole():Bool
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
return this.platformType == PlatformType.CONSOLE;
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function is32Bit():Bool
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
return this.architectures.contains(Architecture.X86);
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function is64Bit():Bool
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
return this.architectures.contains(Architecture.X64);
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function isWindows():Bool
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
return this.target == Platform.WINDOWS;
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function isMac():Bool
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
return this.target == Platform.MAC;
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function isLinux():Bool
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
return this.target == Platform.LINUX;
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function isAndroid():Bool
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
return this.target == Platform.ANDROID;
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function isIOS():Bool
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
return this.target == Platform.IOS;
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-06-03 09:55:35 +00:00
|
|
|
public function isIOSSimulator():Bool
|
|
|
|
{
|
|
|
|
return this.target == Platform.IOS && this.targetFlags.exists("simulator");
|
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function isHashLink():Bool
|
|
|
|
{
|
2024-08-26 22:01:23 +00:00
|
|
|
return this.targetFlags.exists("hl");
|
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function isNeko():Bool
|
|
|
|
{
|
2024-08-26 22:01:23 +00:00
|
|
|
return this.targetFlags.exists("neko");
|
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function isJava():Bool
|
|
|
|
{
|
2024-08-26 22:01:23 +00:00
|
|
|
return this.targetFlags.exists("java");
|
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function isNodeJS():Bool
|
|
|
|
{
|
2024-08-26 22:01:23 +00:00
|
|
|
return this.targetFlags.exists("nodejs");
|
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function isCSharp():Bool
|
|
|
|
{
|
2024-08-26 22:01:23 +00:00
|
|
|
return this.targetFlags.exists("cs");
|
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function isDisplay():Bool
|
|
|
|
{
|
2024-08-26 22:01:23 +00:00
|
|
|
return this.command == "display";
|
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function isDebug():Bool
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
return this.debug;
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function isRelease():Bool
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
return !isDebug();
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-04-16 11:29:08 +00:00
|
|
|
public function isBundle():Bool
|
|
|
|
{
|
|
|
|
return this.targetFlags.exists("bundle") && isAndroid();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getHaxedef(name:String):Null<Dynamic>
|
|
|
|
{
|
2024-08-26 22:01:23 +00:00
|
|
|
return this.haxedefs.get(name);
|
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function setHaxedef(name:String, ?value:String):Void
|
|
|
|
{
|
2024-08-26 22:01:23 +00:00
|
|
|
if (value == null) value = "";
|
|
|
|
|
|
|
|
this.haxedefs.set(name, value);
|
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function unsetHaxedef(name:String):Void
|
|
|
|
{
|
2024-08-26 22:01:23 +00:00
|
|
|
this.haxedefs.remove(name);
|
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function getDefine(name:String):Null<Dynamic>
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
return this.defines.get(name);
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function hasDefine(name:String):Bool
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
return this.defines.exists(name);
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a library to the list of dependencies for the project.
|
|
|
|
* @param name The name of the library to add.
|
|
|
|
* @param version The version of the library to add. Optional.
|
|
|
|
*/
|
|
|
|
public function addHaxelib(name:String, version:String = ""):Void
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
this.haxelibs.push(new Haxelib(name, version));
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* Add a `haxeflag` to the project.
|
|
|
|
*/
|
|
|
|
public function addHaxeFlag(value:String):Void
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
this.haxeflags.push(value);
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* Call a Haxe build macro.
|
|
|
|
*/
|
|
|
|
public function addHaxeMacro(value:String):Void
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
addHaxeFlag('--macro ${value}');
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add an icon to the project.
|
|
|
|
* @param icon The path to the icon.
|
|
|
|
* @param size The size of the icon. Optional.
|
|
|
|
*/
|
|
|
|
public function addIcon(icon:String, ?size:Int):Void
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
this.icons.push(new Icon(icon, size));
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-04-16 11:29:08 +00:00
|
|
|
/**
|
|
|
|
* Add an asset to the game build.
|
|
|
|
* @param path The path the asset is located at.
|
|
|
|
* @param rename The path the asset should be placed.
|
|
|
|
* @param library The asset library to add the asset to. `null` = "default"
|
|
|
|
* @param embed Whether to embed the asset in the executable.
|
|
|
|
* @param padName The name of the Play Assets Delivery that this asset will be added to. (Android only)
|
|
|
|
*/
|
|
|
|
public function addAsset(path:String, ?rename:String, ?library:String, embed:Bool = false, ?padName:String):Void
|
|
|
|
{
|
|
|
|
// path, rename, type, embed, setDefaults
|
2025-05-02 22:59:26 +00:00
|
|
|
if (Path.extension(path) == 'png' && FEATURE_COMPRESSED_TEXTURES.isEnabled(this))
|
|
|
|
{
|
2025-06-03 06:54:53 +00:00
|
|
|
final astcPath:String = "astc-textures/" + path.substr(0, path.length - 3) + "astc";
|
|
|
|
if (!isASTCExcluded(path) && FileSystem.exists(astcPath))
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
path = astcPath;
|
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
if (rename != null) rename = rename.substr(0, rename.length - 3) + "astc";
|
|
|
|
}
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2025-04-27 11:33:34 +00:00
|
|
|
|
2025-04-16 11:29:08 +00:00
|
|
|
var asset = new Asset(path, rename, null, embed, true);
|
|
|
|
@:nullSafety(Off)
|
|
|
|
{
|
|
|
|
asset.library = library ?? "default";
|
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-04-09 04:22:54 +00:00
|
|
|
if (padName != null && isBundle())
|
2025-04-16 11:29:08 +00:00
|
|
|
{
|
|
|
|
asset.deliveryPackName = padName;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.assets.push(asset);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add an entire path of assets to the game build.
|
|
|
|
* @param path The path the assets are located at.
|
|
|
|
* @param rename The path the assets should be placed.
|
|
|
|
* @param library The asset library to add the assets to. `null` = "default"
|
|
|
|
* @param include An optional array to include specific asset names.
|
|
|
|
* @param exclude An optional array to exclude specific asset names.
|
|
|
|
* @param embed Whether to embed the assets in the executable.
|
|
|
|
* @param padName The name of the Play Assets Delivery that this asset path will be added to. (Android only)
|
|
|
|
*/
|
2025-06-03 06:54:53 +00:00
|
|
|
public function addAssetPath(path:String, ?rename:String, library:String, ?include:Array<String>, ?exclude:Array<String>, embed:Bool = false,
|
|
|
|
?padName:String):Void
|
2025-04-16 11:29:08 +00:00
|
|
|
{
|
|
|
|
// Argument parsing.
|
|
|
|
if (path == "") return;
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
if (include == null) include = [];
|
|
|
|
|
|
|
|
if (exclude == null) exclude = [];
|
|
|
|
|
|
|
|
var targetPath = rename ?? path;
|
|
|
|
if (targetPath != "") targetPath += "/";
|
|
|
|
|
|
|
|
// Validate path.
|
2025-05-11 23:43:45 +00:00
|
|
|
if (!sys.FileSystem.exists(path))
|
|
|
|
{
|
|
|
|
error('Could not find asset path "${path}".');
|
|
|
|
}
|
|
|
|
else if (!sys.FileSystem.isDirectory(path))
|
|
|
|
{
|
|
|
|
error('Could not parse asset path "${path}", expected a directory.');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// info(' Found asset path "${path}".');
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
for (file in sys.FileSystem.readDirectory(path))
|
|
|
|
{
|
|
|
|
if (sys.FileSystem.isDirectory('${path}/${file}'))
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// Attempt to recursively add all assets in the directory.
|
2025-05-11 23:43:45 +00:00
|
|
|
if (this.filter(file, ["*"], exclude))
|
|
|
|
{
|
2025-06-03 06:54:53 +00:00
|
|
|
addAssetPath('${path}/${file}', '${targetPath}${file}', library, include, exclude, embed, padName);
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (this.filter(file, include, exclude))
|
|
|
|
{
|
2025-06-03 06:54:53 +00:00
|
|
|
addAsset('${path}/${file}', '${targetPath}${file}', library, embed, padName);
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* Add an asset library to the game build.
|
|
|
|
* @param name The name of the library.
|
|
|
|
* @param embed
|
|
|
|
* @param preload
|
|
|
|
*/
|
|
|
|
public function addAssetLibrary(name:String, embed:Bool = false, preload:Bool = false):Void
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// sourcePath, name, type, embed, preload, generate, prefix
|
2024-08-26 22:01:23 +00:00
|
|
|
var sourcePath = '';
|
2025-05-02 22:59:26 +00:00
|
|
|
this.libraries.push(new Library(sourcePath, name, null, embed, preload, false, ""));
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
//
|
|
|
|
// PROCESS FUNCTIONS
|
|
|
|
//
|
2024-08-26 22:01:23 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A CLI command to run a command in the shell.
|
|
|
|
*/
|
2025-05-11 23:43:45 +00:00
|
|
|
public function buildCLICommand(cmd:String):CLICommand
|
|
|
|
{
|
2024-08-26 22:01:23 +00:00
|
|
|
return CommandHelper.fromSingleString(cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A CLI command to run a Haxe script via `--interp`.
|
|
|
|
*/
|
2025-05-11 23:43:45 +00:00
|
|
|
public function buildHaxeCLICommand(path:String):CLICommand
|
|
|
|
{
|
2024-08-26 22:01:23 +00:00
|
|
|
return CommandHelper.interpretHaxe(path);
|
|
|
|
}
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function getGitCommit():String
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// Cannibalized from GitCommit.hx
|
|
|
|
var process = new sys.io.Process('git', ['rev-parse', 'HEAD']);
|
2025-05-11 23:43:45 +00:00
|
|
|
if (process.exitCode() != 0)
|
|
|
|
{
|
|
|
|
var message = process.stderr.readAll().toString();
|
|
|
|
error('[ERROR] Could not determine current git commit; is this a proper Git repository?');
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
var commitHash:String = process.stdout.readLine();
|
|
|
|
var commitHashSplice:String = commitHash.substr(0, 7);
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
process.close();
|
2024-09-18 20:15:10 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
return commitHashSplice;
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function getGitBranch():String
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// Cannibalized from GitCommit.hx
|
|
|
|
var branchProcess = new sys.io.Process('git', ['rev-parse', '--abbrev-ref', 'HEAD']);
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
if (branchProcess.exitCode() != 0)
|
|
|
|
{
|
|
|
|
var message = branchProcess.stderr.readAll().toString();
|
|
|
|
error('Could not determine current git branch; is this a proper Git repository?');
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
var branchName:String = branchProcess.stdout.readLine();
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
branchProcess.close();
|
2024-09-18 20:15:10 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
return branchName;
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function getGitModified():Bool
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
var branchProcess = new sys.io.Process('git', ['status', '--porcelain']);
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
if (branchProcess.exitCode() != 0)
|
|
|
|
{
|
|
|
|
var message = branchProcess.stderr.readAll().toString();
|
|
|
|
error('Could not determine current git status; is this a proper Git repository?');
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var output:String = '';
|
2025-05-11 23:43:45 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
output = branchProcess.stdout.readLine();
|
|
|
|
}
|
|
|
|
catch (e)
|
|
|
|
{
|
|
|
|
if (e.message == 'Eof')
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// Do nothing.
|
|
|
|
// Eof = No output.
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// Rethrow other exceptions.
|
|
|
|
throw e;
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
branchProcess.close();
|
|
|
|
|
|
|
|
return output.length > 0;
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
//
|
|
|
|
// LOGGING FUNCTIONS
|
|
|
|
//
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* Display an error message. This should stop the build process.
|
|
|
|
*/
|
|
|
|
public function error(message:String):Void
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
Log.error('${message}');
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* Display an info message. This should not interfere with the build process.
|
|
|
|
*/
|
|
|
|
public function info(message:String):Void
|
|
|
|
{
|
|
|
|
if (command != "display")
|
|
|
|
{
|
|
|
|
Log.info('[INFO] ${message}');
|
|
|
|
}
|
|
|
|
}
|
2025-04-17 11:22:45 +00:00
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
/**
|
|
|
|
* Read the contents of the `.env` file into a map.
|
|
|
|
* This is used to store secret keys as environment variables.
|
|
|
|
*/
|
|
|
|
public function readEnvironmentFile(file:String):Null<Map<String, Dynamic>>
|
|
|
|
{
|
|
|
|
if (!FileSystem.exists(file))
|
|
|
|
{
|
|
|
|
info('Environment file does not exist: ${file}');
|
|
|
|
return null;
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2025-04-30 04:31:31 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
var envFile = File.getContent(file);
|
2025-04-17 11:22:45 +00:00
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
if (envFile == null)
|
|
|
|
{
|
|
|
|
info('Failed to parse environment file: ${file}');
|
|
|
|
return null;
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2025-04-17 11:22:45 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
var env = new Map<String, Dynamic>();
|
2025-06-03 06:54:53 +00:00
|
|
|
for (line in envFile.split('\n'))
|
|
|
|
{
|
|
|
|
if (line == "" || line.startsWith("#")) continue;
|
2025-04-17 11:22:45 +00:00
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
var parts = line.split('=');
|
|
|
|
if (parts.length != 2) continue;
|
2025-04-17 11:22:45 +00:00
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
env.set(parts[0], parts[1]);
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2025-04-17 11:22:45 +00:00
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
return env;
|
2025-06-03 06:54:53 +00:00
|
|
|
}
|
2025-04-27 11:33:34 +00:00
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
public function readASTCExclusion():Void
|
|
|
|
{
|
2025-04-27 11:33:34 +00:00
|
|
|
astcExcludes = File.getContent('./compression-excludes.txt').trim().split('\n');
|
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
for (i in 0...astcExcludes.length)
|
2025-06-03 06:54:53 +00:00
|
|
|
astcExcludes[i] = astcExcludes[i].trim();
|
|
|
|
}
|
2025-04-27 11:33:34 +00:00
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
public function isASTCExcluded(filePath:String):Bool
|
|
|
|
{
|
|
|
|
for (exclusion in astcExcludes)
|
|
|
|
{
|
|
|
|
if (exclusion.endsWith("/*"))
|
|
|
|
{
|
2025-04-27 11:33:34 +00:00
|
|
|
var normalizedFilePath = Path.normalize(filePath);
|
|
|
|
var normalizedExclusion = Path.normalize(exclusion.substr(0, exclusion.length - 2));
|
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
if (normalizedFilePath.startsWith(normalizedExclusion)) return true;
|
2025-04-27 11:33:34 +00:00
|
|
|
}
|
2025-06-03 06:54:53 +00:00
|
|
|
else if (exclusion.endsWith("/"))
|
|
|
|
{
|
2025-04-27 11:33:34 +00:00
|
|
|
var normalizedExclusion = Path.normalize(exclusion);
|
|
|
|
var fileDirectory = Path.directory(Path.normalize(filePath));
|
|
|
|
|
2025-06-03 06:54:53 +00:00
|
|
|
if (fileDirectory == normalizedExclusion) return true;
|
2025-04-27 11:33:34 +00:00
|
|
|
}
|
2025-06-03 06:54:53 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (filePath == exclusion) return true;
|
2025-04-27 11:33:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-02 22:59:26 +00:00
|
|
|
return false;
|
2025-06-03 06:54:53 +00:00
|
|
|
}
|
2025-05-03 13:32:36 +00:00
|
|
|
|
|
|
|
public function runASTCCompressor():Void
|
|
|
|
{
|
|
|
|
info('Compressing ASTC textures...');
|
|
|
|
|
|
|
|
var args:Array<String> = ['run', 'astc-compressor'];
|
|
|
|
args = args.concat(['-i', './assets']);
|
|
|
|
args = args.concat(['-o', './astc-textures/assets/']);
|
|
|
|
args = args.concat(['-blocksize', ASTC_BLOCKSIZE]);
|
|
|
|
args = args.concat(['-quality', ASTC_QUALITY]);
|
|
|
|
args = args.concat(['-excludes', './compression-excludes.txt']);
|
|
|
|
|
|
|
|
Sys.command('haxelib', args);
|
|
|
|
|
|
|
|
info('Finished compressing ASTC textures!');
|
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An object representing a feature flag, which can be enabled or disabled.
|
|
|
|
* Includes features such as automatic generation of compile defines and inversion.
|
|
|
|
*/
|
2025-05-11 23:43:45 +00:00
|
|
|
abstract FeatureFlag(String)
|
|
|
|
{
|
|
|
|
static final INVERSE_PREFIX:String = "NO_";
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
public function new(input:String)
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
this = input;
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
@:from
|
|
|
|
public static function fromString(input:String):FeatureFlag
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
return new FeatureFlag(input);
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enable/disable a feature flag if it is unset, and handle the inverse flag.
|
|
|
|
* Doesn't override a feature flag that was set explicitly.
|
|
|
|
* @param enableByDefault Whether to enable this feature flag if it is unset.
|
|
|
|
*/
|
|
|
|
public function apply(project:Project, enableByDefault:Bool = false):Void
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// TODO: Name this function better?
|
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
if (isEnabled(project))
|
|
|
|
{
|
|
|
|
// If this flag was already enabled, disable the inverse.
|
|
|
|
project.info('Enabling feature flag ${this}');
|
|
|
|
getInverse().disable(project, false);
|
|
|
|
}
|
|
|
|
else if (getInverse().isEnabled(project))
|
|
|
|
{
|
|
|
|
// If the inverse flag was already enabled, disable this flag.
|
|
|
|
project.info('Disabling feature flag ${this}');
|
|
|
|
disable(project, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (enableByDefault)
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// Enable this flag if it was unset, and disable the inverse.
|
|
|
|
project.info('Enabling feature flag ${this}');
|
|
|
|
enable(project, true);
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// Disable this flag if it was unset, and enable the inverse.
|
|
|
|
project.info('Disabling feature flag ${this}');
|
|
|
|
disable(project, true);
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* Enable this feature flag by setting the appropriate compile define.
|
|
|
|
*
|
|
|
|
* @param project The project to modify.
|
|
|
|
* @param andInverse Also disable the feature flag's inverse.
|
|
|
|
*/
|
|
|
|
public function enable(project:Project, andInverse:Bool = true)
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
project.setHaxedef(this, "");
|
2025-05-11 23:43:45 +00:00
|
|
|
if (andInverse)
|
|
|
|
{
|
|
|
|
getInverse().disable(project, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Disable this feature flag by removing the appropriate compile define.
|
|
|
|
*
|
|
|
|
* @param project The project to modify.
|
|
|
|
* @param andInverse Also enable the feature flag's inverse.
|
|
|
|
*/
|
|
|
|
public function disable(project:Project, andInverse:Bool = true)
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
project.unsetHaxedef(this);
|
2025-05-11 23:43:45 +00:00
|
|
|
if (andInverse)
|
|
|
|
{
|
|
|
|
getInverse().enable(project, false);
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* Query if this feature flag is enabled.
|
|
|
|
* @param project The project to query.
|
|
|
|
*/
|
|
|
|
public function isEnabled(project:Project):Bool
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
// Check both Haxedefs and Defines for this flag.
|
|
|
|
return project.haxedefs.exists(this) || project.defines.exists(this);
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* Query if this feature flag's inverse is enabled.
|
|
|
|
*/
|
|
|
|
public function isDisabled(project:Project):Bool
|
|
|
|
{
|
2025-05-02 22:59:26 +00:00
|
|
|
return getInverse().isEnabled(project);
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
|
2025-05-11 23:43:45 +00:00
|
|
|
/**
|
|
|
|
* Return the inverse of this feature flag.
|
|
|
|
* @return A new feature flag that is the inverse of this one.
|
|
|
|
*/
|
|
|
|
public function getInverse():FeatureFlag
|
|
|
|
{
|
|
|
|
if (this.startsWith(INVERSE_PREFIX))
|
|
|
|
{
|
|
|
|
return this.substring(INVERSE_PREFIX.length);
|
2025-05-02 22:59:26 +00:00
|
|
|
}
|
|
|
|
return INVERSE_PREFIX + this;
|
2025-05-11 23:43:45 +00:00
|
|
|
}
|
2024-08-26 22:01:23 +00:00
|
|
|
}
|