commit 7c65eb4dcb8ba019258ae4675d40a43b24e2426d Author: Randall Winkhart Date: Tue Mar 10 16:53:11 2026 -0400 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1470da5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/.clangd +/build +/resources +/.lock* diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e5ce0f3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,23 @@ +MIT License + +Copyright (c) 2026 hilariouspig + +THIS LICENSE DOES NOT APPLY TO ANY ".png" FILES IN THIS REPOSITORY. + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a560595 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# Maan On My Wrist XL +This is an unofficial port of the [Maan On My Wrist](https://apps.rebble.io/en_US/application/557724772d93bc0eae00004c?native=false&query=maan§ion=watchfaces) watchface to the new Pebble Time/Round 2 devices. + +Since the original watchface is **NOT** open source, this port could be more accurately described as a reverse-engineered recreation. + +# Differences From The Original +- Re-scaled to look better on the larger displays of the Pebble Time/Round 2 +- Some of the extra screen space is used to display the date, the battery level, and bluetooth status +- Original creature part modifications (for the pre-compiled version available on the Rebble app store) + - Some creature parts that resulted in broken-looking creatures were overhauled + - Any creature parts that previously had cut-off details to fit on the smaller display have been extended + - Some creature parts removed by the original developer (to conserve space) have been re-added + - Most creature parts now have manually placed accent colors +- Creature parts are now dynamically and randomly re-colored when loaded in +- A moving sun/moon have been added to reflect the real day/night cycle (also to fill extra screen space) +- This port is not yet compatible with 144x168 and 180x180 Pebbles + - The original [Maan On My Wrist](https://apps.rebble.io/en_US/application/557724772d93bc0eae00004c?native=false&query=maan§ion=watchfaces) is still perfectly silly on 144x168 watches! + - 180x180 (OG Pebble Time Round) may be supported in the future, since it currently has no + functional version of Maan On My Wrist + +# Development +1. Install the [Pebble SDK](https://developer.repebble.com/sdk/) +2. Clone this repo +3. `pebble build` (some headers needed to satisfy your IDE are generated on first build) +4. If using `clangd`, run `./tools/clangd.zsh` to generate a `.clangd` file to fix various error notifications +5. Hack away and test with `pebble build && pebble install --emulator emery` diff --git a/jshintrc b/jshintrc new file mode 100644 index 0000000..4c5376d --- /dev/null +++ b/jshintrc @@ -0,0 +1,46 @@ + +/* + * Example jshint configuration file for Pebble development. + * + * Check out the full documentation at http://www.jshint.com/docs/options/ + */ +{ + // Declares the existence of the globals available in PebbleKit JS. + "globals": {"console": true, "setTimeout": true, "setInterval": true, "Int8Array": true, "Uint8Array": true, "Uint8ClampedArray": true, "Int16Array": true, "Uint16Array": true, "Int32Array": true, "Uint32Array": true, "Float32Array": true, "Float64Array": true, "Pebble": true, "WebSocket": true, "XMLHttpRequest": true, "navigator": true, "localStorage": true, "require": true, "exports": true, "module": true}, + + // Do not mess with standard JavaScript objects (Array, Date, etc) + "freeze": true, + + // Do not use eval! Keep this warning turned on (ie: false) + "evil": false, + + /* + * The options below are more style/developer dependent. + * Customize to your liking. + */ + + // All variables should be in camelcase - too specific for CloudPebble builds to fail + // "camelcase": true, + + // Do not allow blocks without { } - too specific for CloudPebble builds to fail. + // "curly": true, + + // Prohibits the use of immediate function invocations without wrapping them in parentheses + "immed": true, + + // Don't enforce indentation, because it's not worth failing builds over + // (especially given our somewhat lacklustre support for it) + "indent": false, + + // Do not use a variable before it's defined + "latedef": "nofunc", + + // Spot undefined variables + "undef": "true", + + // Spot unused variables + "unused": "true", + + // Enable ES6 syntax (const, let, arrow functions, etc) + "esversion": 6 +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..a7cef15 --- /dev/null +++ b/package.json @@ -0,0 +1,554 @@ +{ + "author": "hilariouspig", + "dependencies": {}, + "keywords": [], + "name": "maan-on-my-wrist-xl", + "pebble": { + "displayName": "Maan On My Wrist XL", + "enableMultiJS": true, + "messageKeys": [], + "projectType": "native", + "resources": { + "media": [ + { + "file": "images/b001.png", + "memoryFormat": "Smallest", + "name": "B001", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h001.png", + "memoryFormat": "Smallest", + "name": "H001", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b002.png", + "memoryFormat": "Smallest", + "name": "B002", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h002.png", + "memoryFormat": "Smallest", + "name": "H002", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b003.png", + "memoryFormat": "Smallest", + "name": "B003", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h003.png", + "memoryFormat": "Smallest", + "name": "H003", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b018.png", + "memoryFormat": "Smallest", + "name": "B018", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h004.png", + "memoryFormat": "Smallest", + "name": "H004", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b004.png", + "memoryFormat": "Smallest", + "name": "B004", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h005.png", + "memoryFormat": "Smallest", + "name": "H005", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h006.png", + "memoryFormat": "Smallest", + "name": "H006", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h007.png", + "memoryFormat": "Smallest", + "name": "H007", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b005.png", + "memoryFormat": "Smallest", + "name": "B005", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h008.png", + "memoryFormat": "Smallest", + "name": "H008", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h009.png", + "memoryFormat": "Smallest", + "name": "H009", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h010.png", + "memoryFormat": "Smallest", + "name": "H010", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b006.png", + "memoryFormat": "Smallest", + "name": "B006", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h011.png", + "memoryFormat": "Smallest", + "name": "H011", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b019.png", + "memoryFormat": "Smallest", + "name": "B019", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h012.png", + "memoryFormat": "Smallest", + "name": "H012", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h013.png", + "memoryFormat": "Smallest", + "name": "H013", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h014.png", + "memoryFormat": "Smallest", + "name": "H014", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b007.png", + "memoryFormat": "Smallest", + "name": "B007", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h015.png", + "memoryFormat": "Smallest", + "name": "H015", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h016.png", + "memoryFormat": "Smallest", + "name": "H016", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b020.png", + "memoryFormat": "Smallest", + "name": "B020", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b008.png", + "memoryFormat": "Smallest", + "name": "B008", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b009.png", + "memoryFormat": "Smallest", + "name": "B009", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b010.png", + "memoryFormat": "Smallest", + "name": "B010", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b021.png", + "memoryFormat": "Smallest", + "name": "B021", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b011.png", + "memoryFormat": "Smallest", + "name": "B011", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b012.png", + "memoryFormat": "Smallest", + "name": "B012", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b013.png", + "memoryFormat": "Smallest", + "name": "B013", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b022.png", + "memoryFormat": "Smallest", + "name": "B022", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b014.png", + "memoryFormat": "Smallest", + "name": "B014", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b015.png", + "memoryFormat": "Smallest", + "name": "B015", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b016.png", + "memoryFormat": "Smallest", + "name": "B016", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/xb001.png", + "memoryFormat": "Smallest", + "name": "XB001", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/xb002.png", + "memoryFormat": "Smallest", + "name": "XB002", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/xb003.png", + "memoryFormat": "Smallest", + "name": "XB003", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/xb004.png", + "memoryFormat": "Smallest", + "name": "XB004", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h017.png", + "memoryFormat": "Smallest", + "name": "H017", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h018.png", + "memoryFormat": "Smallest", + "name": "H018", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h019.png", + "memoryFormat": "Smallest", + "name": "H019", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h020.png", + "memoryFormat": "Smallest", + "name": "H020", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h021.png", + "memoryFormat": "Smallest", + "name": "H021", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/h022.png", + "memoryFormat": "Smallest", + "name": "H022", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + }, + { + "file": "images/b017.png", + "memoryFormat": "Smallest", + "name": "B017", + "spaceOptimization": "storage", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "type": "bitmap" + } + ] + }, + "sdkVersion": "3", + "targetPlatforms": [ + "emery", + "gabbro" + ], + "uuid": "6ef9ba03-0d4e-44f3-b397-f46117fd313a", + "watchapp": { + "watchface": false + } + }, + "version": "1.0.0" +} diff --git a/src/c/main.c b/src/c/main.c new file mode 100644 index 0000000..e2c0f1c --- /dev/null +++ b/src/c/main.c @@ -0,0 +1,138 @@ +#include +#include "palette_manip.h" + +// declare general static pointers +static Window *s_main_window; +static BitmapLayer *s_guy_head_layer; +static BitmapLayer *s_guy_butt_layer; + +// declare silly guy parts +static GColor8 s_random_color_current; +static GColor8 s_random_color_next; +static GBitmap *s_head_current; +static GBitmap *s_butt_current; +static GBitmap *s_head_next; +static GBitmap *s_butt_next; + +// declare lookup tables +static const uint32_t randomHeadPool[] = { + RESOURCE_ID_H001, RESOURCE_ID_H002, RESOURCE_ID_H003, + RESOURCE_ID_H004, RESOURCE_ID_H005, RESOURCE_ID_H006, + RESOURCE_ID_H007, RESOURCE_ID_H008, RESOURCE_ID_H009, + RESOURCE_ID_H010, RESOURCE_ID_H011, RESOURCE_ID_H012, + RESOURCE_ID_H013, RESOURCE_ID_H014, RESOURCE_ID_H015, + RESOURCE_ID_H016, RESOURCE_ID_H017, RESOURCE_ID_H018, + RESOURCE_ID_H019, RESOURCE_ID_H020, RESOURCE_ID_H021, + RESOURCE_ID_H022 +}; +static const uint32_t randomButtPool[] = { + RESOURCE_ID_B001, RESOURCE_ID_B002, RESOURCE_ID_B003, + RESOURCE_ID_B004, RESOURCE_ID_B005, RESOURCE_ID_B006, + RESOURCE_ID_B007, RESOURCE_ID_B008, RESOURCE_ID_B009, + RESOURCE_ID_B010, RESOURCE_ID_B011, RESOURCE_ID_B012, + RESOURCE_ID_B013, RESOURCE_ID_B014, RESOURCE_ID_B015, + RESOURCE_ID_B016, RESOURCE_ID_B017, RESOURCE_ID_B018, + RESOURCE_ID_B019, RESOURCE_ID_B020, RESOURCE_ID_B021, + RESOURCE_ID_B022, RESOURCE_ID_XB001, RESOURCE_ID_XB002, + RESOURCE_ID_XB003, RESOURCE_ID_XB004 +}; +static const GColor8 darkBGColorPool[] = { + // Red + GColorFolly, + GColorRed, + // Orange + GColorOrange, + GColorRajah, + GColorSunsetOrange, + // Yellow + GColorChromeYellow, + GColorIcterine, + GColorPastelYellow, + GColorYellow, + // Green + GColorInchworm, + GColorJaegerGreen, + GColorKellyGreen, + GColorMintGreen, + // Blue + GColorElectricBlue, + GColorTiffanyBlue, + GColorVividCerulean, + // Purple + GColorLavenderIndigo, + GColorPurpureus, + GColorRichBrilliantLavender, + // Pink + GColorBrilliantRose, + GColorMelon, + // Brown + GColorRoseVale +}; + +// define contents of the Window upon load +static void main_window_load(Window *window) { + // format silly guy layers + s_guy_head_layer = bitmap_layer_create(GRect(PBL_IF_ROUND_ELSE(0, -30), PBL_IF_ROUND_ELSE(0, -16), 260, 115)); + s_guy_butt_layer = bitmap_layer_create(GRect(PBL_IF_ROUND_ELSE(0, -30), PBL_IF_ROUND_ELSE(145, 129), 260, 115)); + bitmap_layer_set_compositing_mode(s_guy_head_layer, GCompOpSet); + bitmap_layer_set_background_color(s_guy_head_layer, GColorBlack); + bitmap_layer_set_bitmap(s_guy_head_layer, s_head_current); + bitmap_layer_set_compositing_mode(s_guy_butt_layer, GCompOpSet); + bitmap_layer_set_background_color(s_guy_butt_layer, GColorBlack); + bitmap_layer_set_bitmap(s_guy_butt_layer, s_butt_current); + + // add silly guy layers as children to window + Layer *window_layer = window_get_root_layer(window); + layer_add_child(window_layer, bitmap_layer_get_layer(s_guy_head_layer)); + layer_add_child(window_layer, bitmap_layer_get_layer(s_guy_butt_layer)); +} + +// free memory on Window close; +// this means matching all "_create"'s from main_window_load with "_destroy" +static void main_window_unload(Window *window) { + bitmap_layer_destroy(s_guy_head_layer); + bitmap_layer_destroy(s_guy_butt_layer); +} + +// set up the app on launch (don't put app logic in here); +static void init() { + // create main Window element and assign to pointer + s_main_window = window_create(); + + // set handlers to manage the elements inside the Window + window_set_window_handlers(s_main_window, (WindowHandlers) { + .load = main_window_load, + .unload = main_window_unload + }); + + // load initial batch of silly guy parts into memory + s_head_current = gbitmap_create_with_resource(randomHeadPool[rand()%22]); + s_butt_current = gbitmap_create_with_resource(randomButtPool[rand()%26]); + s_head_next = gbitmap_create_with_resource(randomHeadPool[rand()%22]); + s_butt_next = gbitmap_create_with_resource(randomButtPool[rand()%26]); + + // pick starting colors + s_random_color_current = darkBGColorPool[rand()%22]; + s_random_color_next = darkBGColorPool[rand()%22]; + replace_gbitmap_color(GColorGreen, s_random_color_current, s_head_current, NULL); + replace_gbitmap_color(GColorGreen, s_random_color_current, s_butt_current, NULL); + + // show the Window on the watch, with animated=true + window_stack_push(s_main_window, true); +} + +// free memory on app exit; +// this means matching all "_create"'s from init() with "_destroy" +static void deinit() { + gbitmap_destroy(s_head_current); + gbitmap_destroy(s_butt_current); + gbitmap_destroy(s_head_next); + gbitmap_destroy(s_butt_next); + window_destroy(s_main_window); +} + +int main(void) { + init(); + app_event_loop(); + deinit(); +} diff --git a/src/c/palette_manip.c b/src/c/palette_manip.c new file mode 100644 index 0000000..09963e7 --- /dev/null +++ b/src/c/palette_manip.c @@ -0,0 +1,41 @@ +// TAKEN FROM https://github.com/rebootsramblings/GBitmap-Colour-Palette-Manipulator + +#include "palette_manip.h" + +#ifdef PBL_COLOR + +int get_num_palette_colors(GBitmap *b){ + GBitmapFormat format = gbitmap_get_format(b); + switch (format) { + case GBitmapFormat1Bit: return 0; + case GBitmapFormat8Bit: return 0; + case GBitmapFormat1BitPalette: return 2; + case GBitmapFormat2BitPalette: return 4; + case GBitmapFormat4BitPalette: return 16; + default: return 0; + } +} + +void replace_gbitmap_color(GColor color_to_replace, GColor replace_with_color, GBitmap *im, BitmapLayer *bml){ + //First determine what the number of colors in the palette + int num_palette_items = get_num_palette_colors(im); + + //Get the gbitmap's current palette + GColor *current_palette = gbitmap_get_palette(im); + + //Iterate through the palette finding the color we want to replace and replacing + //it with the new color + for(int i = 0; i < num_palette_items; i++){ + if ((color_to_replace.argb & 0x3F)==(current_palette[i].argb & 0x3F)){ + current_palette[i].argb = (current_palette[i].argb & 0xC0)| (replace_with_color.argb & 0x3F); + } + } + + //Mark the bitmaplayer dirty + if(bml != NULL){ + layer_mark_dirty(bitmap_layer_get_layer(bml)); + } + +} + +#endif \ No newline at end of file diff --git a/src/c/palette_manip.h b/src/c/palette_manip.h new file mode 100644 index 0000000..50d48f3 --- /dev/null +++ b/src/c/palette_manip.h @@ -0,0 +1,7 @@ +// TAKEN FROM https://github.com/rebootsramblings/GBitmap-Colour-Palette-Manipulator + +#include + +#ifdef PBL_COLOR +void replace_gbitmap_color(GColor color_to_replace, GColor replace_with_color, GBitmap *im, BitmapLayer *bml); +#endif \ No newline at end of file diff --git a/tools/clangd.zsh b/tools/clangd.zsh new file mode 100755 index 0000000..e9d46bf --- /dev/null +++ b/tools/clangd.zsh @@ -0,0 +1,15 @@ +#!/usr/bin/env zsh +echo "CompileFlags: + Add: + [ + -xc, + -nostdinc, + -DPBL_COLOR, + -I${HOME}/.pebble-sdk/SDKs/current/sdk-core/pebble/emery/include, + -include/home/cuan/gitrepos/Maan-On-My-Wrist-XL/build/include/message_keys.auto.h, + -I$(pwd)/build/emery, + -include${HOME}/.pebble-sdk/SDKs/current/toolchain/arm-none-eabi/arm-none-eabi/include/stdint.h, + -include${HOME}/.pebble-sdk/SDKs/current/toolchain/arm-none-eabi/arm-none-eabi/include/stdlib.h, + -include${HOME}/.pebble-sdk/SDKs/current/toolchain/arm-none-eabi/lib/gcc/arm-none-eabi/14.2.1/include/stddef.h, + -include${HOME}/.pebble-sdk/SDKs/current/toolchain/arm-none-eabi/lib/gcc/arm-none-eabi/14.2.1/include/stdbool.h, + ]" > ./.clangd diff --git a/tools/magick.zsh b/tools/magick.zsh new file mode 100755 index 0000000..a7ce4a9 --- /dev/null +++ b/tools/magick.zsh @@ -0,0 +1,33 @@ +#!/usr/bin/env zsh + +# THIS IS A LEGACY TOOL THAT WAS USED FOR THE INITIAL +# ASSET EXTRACTION - ASSETS HAVE SINCE BEEN HEAVILY +# MODIFIED, MAKING THIS SCRIPT PRETTY USELESS + +if [[ $# -lt 2 ]]; then + echo "Usage: $0 " + exit 1 +fi + +if [[ $2 == "top" ]]; then + gravity="South" +elif [[ $2 == "bottom" ]]; then + gravity="North" +else + echo "Usage: $0 " + exit 1 +fi + +for file in $1/*; do + magick "$file" -gravity $gravity -chop 0x10 "$file" + magick "$file" -transparent Black PNG24:"$file" + magick "$file" -fill "rgb(0,255,0)" -opaque White "$file" + magick "$file" -gravity Center -background None -compose Copy -extent 260x $file + # Bar is commented out for an experiment with rendering in real time on the watch + #magick "$file" -gravity $gravity -background White -splice 0x15 $file + if [[ $2 == "top" ]]; then + magick "$file" -gravity North -background None -splice 0x41 $file + else + magick "$file" -gravity South -background None -splice 0x41 $file + fi +done diff --git a/tools/zopfli.zsh b/tools/zopfli.zsh new file mode 100755 index 0000000..9324764 --- /dev/null +++ b/tools/zopfli.zsh @@ -0,0 +1,7 @@ +#!/usr/bin/env zsh + +# ALWAYS USE ZOPFLI TO CRUSH PNGS AS MUCH AS POSSIBLE BEFORE SHIPPING + +for file in **/*; do + zopflipng -y --iterations=500 --filters=01234mepb --lossy_8bit --lossy_transparent $file $file & +done diff --git a/wscript b/wscript new file mode 100644 index 0000000..d58beab --- /dev/null +++ b/wscript @@ -0,0 +1,52 @@ +# +# This file is the default set of rules to compile a Pebble project. +# +# Feel free to customize this to your needs. +# + +import os.path +try: + from sh import CommandNotFound, jshint, cat, ErrorReturnCode_2 + hint = jshint +except (ImportError, Exception): + hint = None + +top = '.' +out = 'build' + + +def options(ctx): + ctx.load('pebble_sdk') + + +def configure(ctx): + ctx.load('pebble_sdk') + + +def build(ctx): + if False and hint is not None: + try: + hint(['--config', 'pebble-jshintrc'] + [node.abspath() for node in ctx.path.ant_glob("src/**/*.js")], _tty_out=False) # no tty because there are none in the cloudpebble sandbox. + except ErrorReturnCode_2 as e: + ctx.fatal("\nJavaScript linting failed (you can disable this in Project Settings):\n" + e.stdout) + + ctx.load('pebble_sdk') + + build_worker = os.path.exists('worker_src') + binaries = [] + + for p in ctx.env.TARGET_PLATFORMS: + ctx.set_env(ctx.all_envs[p]) + ctx.set_group(ctx.env.PLATFORM_NAME) + app_elf = '{}/pebble-app.elf'.format(ctx.env.BUILD_DIR) + ctx.pbl_program(source=ctx.path.ant_glob('src/c/**/*.c'), target=app_elf) + + if build_worker: + worker_elf = '{}/pebble-worker.elf'.format(ctx.env.BUILD_DIR) + binaries.append({'platform': p, 'app_elf': app_elf, 'worker_elf': worker_elf}) + ctx.pbl_worker(source=ctx.path.ant_glob('worker_src/c/**/*.c'), target=worker_elf) + else: + binaries.append({'platform': p, 'app_elf': app_elf}) + + ctx.set_group('bundle') + ctx.pbl_bundle(binaries=binaries, js=ctx.path.ant_glob(['src/pkjs/**/*.js', 'src/pkjs/**/*.json']), js_entry_file='src/pkjs/index.js')