Initial commit

This commit is contained in:
2026-03-10 16:53:11 -04:00
commit 7c65eb4dcb
12 changed files with 946 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
/.clangd
/build
/resources
/.lock*

23
LICENSE Normal file
View File

@@ -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.

26
README.md Normal file
View File

@@ -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&section=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&section=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`

46
jshintrc Normal file
View File

@@ -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
}

554
package.json Normal file
View File

@@ -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"
}

138
src/c/main.c Normal file
View File

@@ -0,0 +1,138 @@
#include <pebble.h>
#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();
}

41
src/c/palette_manip.c Normal file
View File

@@ -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

7
src/c/palette_manip.h Normal file
View File

@@ -0,0 +1,7 @@
// TAKEN FROM https://github.com/rebootsramblings/GBitmap-Colour-Palette-Manipulator
#include <pebble.h>
#ifdef PBL_COLOR
void replace_gbitmap_color(GColor color_to_replace, GColor replace_with_color, GBitmap *im, BitmapLayer *bml);
#endif

15
tools/clangd.zsh Executable file
View File

@@ -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

33
tools/magick.zsh Executable file
View File

@@ -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 <dir> <half (top/bottom)>"
exit 1
fi
if [[ $2 == "top" ]]; then
gravity="South"
elif [[ $2 == "bottom" ]]; then
gravity="North"
else
echo "Usage: $0 <dir> <half (top/bottom)>"
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

7
tools/zopfli.zsh Executable file
View File

@@ -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

52
wscript Normal file
View File

@@ -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')