initial
This commit is contained in:
commit
8ec31da055
163
README.md
Normal file
163
README.md
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
# libPicrew
|
||||||
|
|
||||||
|
a NixOS library for declaritively building [Picrews](https://picrew.me/en/image_maker/229486).
|
||||||
|
|
||||||
|
a picrew is a paper-doll-esque website for building avatars, but i really wanted to be able to declaritively define mine as part of my operating system configuration.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
this flake can be added as an input, and its library functions accessed:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
description = "Some Flake";
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs";
|
||||||
|
libpicrew.url = "git+https://git.avery.garden/thorn/libPicrew?ref=mistress";
|
||||||
|
};
|
||||||
|
outputs = { nixpkgs, ... }@inputs: {
|
||||||
|
# avaliable under inputs.libpicrew.lib
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
this flake exposes a single meta-library function, `mkLibPicrew`, which takes an attribute set with the following items, and returns the actual library:
|
||||||
|
|
||||||
|
- `pkgs`
|
||||||
|
- `images`
|
||||||
|
- `ordering`
|
||||||
|
|
||||||
|
`pkgs` is the package set it will pull its dependencies from, `images` is a path to an image set to use (described below), and `ordering` is a list of strings to use for Z-layering (later items are layered on top of earlier ones).
|
||||||
|
|
||||||
|
```
|
||||||
|
let libPicrew = inputs.libpicrew.lib.mkLibPicrew {
|
||||||
|
inherit pkgs;
|
||||||
|
images = ./picrew_images;
|
||||||
|
ordering = [
|
||||||
|
"bg"
|
||||||
|
"skin"
|
||||||
|
"hair"
|
||||||
|
"eyes"
|
||||||
|
"mouth"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
the `images` folder can be gotten through [unethical and dark arts](https://mincerafter42.github.io/picrew-download-bookmarklet/), which will produce a `.ora` file that can be unzipped to produce a `data` subdirectory containing the images needed.
|
||||||
|
|
||||||
|
each subdirectory and file will need to be renamed, such that the outermost directories match each item in `ordering`, with the nested items allowing any format.
|
||||||
|
|
||||||
|
`mkLibPicrew` creates an attribute set with two items, `renderPicrew` and `renderPicrews`
|
||||||
|
|
||||||
|
to use each we need to define some `defaults` and some `parts`:
|
||||||
|
|
||||||
|
a `default` is an attribute set containing variables used in the `parts`, and is intended for items such as skin colour, hair colour, and eye colour that multiple layers or items may share a naming scheme for:
|
||||||
|
|
||||||
|
```
|
||||||
|
thornDefaults = {
|
||||||
|
hair = "black";
|
||||||
|
skin = "pale";
|
||||||
|
eyes = "hazel";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
a `part` is a subset of a full picrew image, that contains a grouping of items, for example an outfit, a hairstyle, or an expression.
|
||||||
|
|
||||||
|
they are functions that take a set of defaults and produce an attribute set where the attribute names correspond to directories in the `images` folder, and the values correspond to files (when appended with `.png`):
|
||||||
|
|
||||||
|
```
|
||||||
|
base = defs: {
|
||||||
|
bg = "darkpink";
|
||||||
|
skin = defs.skin;
|
||||||
|
nose = "large";
|
||||||
|
};
|
||||||
|
|
||||||
|
maid_outfit = defs: {
|
||||||
|
right_sleeve.maid = "colour1";
|
||||||
|
left_sleeve.maid = "colour1";
|
||||||
|
right_hand.closed = defs.skin;
|
||||||
|
left_hand.closed = defs.skin;
|
||||||
|
outer_shirt = "black_maid";
|
||||||
|
ears.maid_band = "colour1";
|
||||||
|
};
|
||||||
|
|
||||||
|
hair_mid = defs: {
|
||||||
|
hair_back.mid = defs.hair;
|
||||||
|
fringe.mildly_jagged = defs.hair;
|
||||||
|
};
|
||||||
|
|
||||||
|
outfit = defs: {
|
||||||
|
earrings = "red_rose";
|
||||||
|
shirt.highneck_sweater = "colour2";
|
||||||
|
};
|
||||||
|
|
||||||
|
expression_bored = defs: {
|
||||||
|
mouth = "small_sad";
|
||||||
|
eyebrows.large_bushy = defs.hair;
|
||||||
|
eyes.to_the_left = defs.eyes;
|
||||||
|
eye_glint = "mid";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### `renderPicrew`
|
||||||
|
|
||||||
|
`renderPicrew` a set of defaults, a list of parts, and a filename, and produces an image. the argument is an attribute set of the following items:
|
||||||
|
|
||||||
|
- `name`, the filename to use (will have `.png` appended)
|
||||||
|
- `parts`, a list of parts to apply
|
||||||
|
- `defaults`, the defaults to use, defaults to `{}`
|
||||||
|
- `src`, the image source to use, defaults to that passed to `mkLibPicrew`
|
||||||
|
- `ordering`, the layer order to use, defaults to that passed to `mkLibPicrew`
|
||||||
|
|
||||||
|
it produces a derivation that builds the image:
|
||||||
|
|
||||||
|
```
|
||||||
|
packages.maid-picrew = renderPicrew {
|
||||||
|
name = "maid";
|
||||||
|
defaults = thornDefaults;
|
||||||
|
parts = [
|
||||||
|
base
|
||||||
|
hair_mid
|
||||||
|
maid_outfit
|
||||||
|
expression_bored
|
||||||
|
];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `renderPicrews`
|
||||||
|
|
||||||
|
this works similar to the above, except it applies the same defaults to multiple sets of parts to create multiple images, it takes three arguments (seperate arguments, not a set):
|
||||||
|
|
||||||
|
- `name`, the package sets name
|
||||||
|
- `defs`, the defaults to apply
|
||||||
|
- `specs`, a list of attribute sets defining each image
|
||||||
|
|
||||||
|
each item in specs has a `name` (the filename), and `parts` (a list of parts to use):
|
||||||
|
|
||||||
|
```
|
||||||
|
packages.thornsPicrews = renderPicrews
|
||||||
|
"thornsPicrews"
|
||||||
|
thornDefaults
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name = "regular";
|
||||||
|
parts = [
|
||||||
|
base
|
||||||
|
hair_mid
|
||||||
|
outfit
|
||||||
|
expression_bored
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "maid";
|
||||||
|
parts = [
|
||||||
|
base
|
||||||
|
hair_mid
|
||||||
|
maid_outfit
|
||||||
|
expression_bored
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
```
|
6
flake.nix
Normal file
6
flake.nix
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
description = "A Nix library for creating Picrew derivations";
|
||||||
|
outputs = { ... }: {
|
||||||
|
lib = import ./picrew.nix;
|
||||||
|
};
|
||||||
|
}
|
77
picrew.nix
Normal file
77
picrew.nix
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
let
|
||||||
|
|
||||||
|
mergeSets = defaults: parts:
|
||||||
|
builtins.foldl'
|
||||||
|
(a: b: a // b)
|
||||||
|
{}
|
||||||
|
(builtins.map (f: f defaults) parts);
|
||||||
|
|
||||||
|
setToFilePaths = ordering: parts:
|
||||||
|
let
|
||||||
|
|
||||||
|
grabPaths = item: path:
|
||||||
|
if (builtins.isString item) then
|
||||||
|
["${builtins.concatStringsSep "/" path}/${item}.png"]
|
||||||
|
else
|
||||||
|
builtins.concatMap
|
||||||
|
(p: grabPaths item.${p} (path ++ [p]))
|
||||||
|
(builtins.attrNames item);
|
||||||
|
|
||||||
|
initial = spec: order:
|
||||||
|
builtins.concatMap
|
||||||
|
(o: if builtins.hasAttr o spec then
|
||||||
|
grabPaths spec.${o} [o]
|
||||||
|
else [])
|
||||||
|
order;
|
||||||
|
|
||||||
|
|
||||||
|
in
|
||||||
|
initial parts ordering;
|
||||||
|
|
||||||
|
mkLibPicrew = { pkgs, ... }@args: rec {
|
||||||
|
renderPicrew = mkRenderPicrew args;
|
||||||
|
renderPicrews = name: defs: specs:
|
||||||
|
pkgs.buildEnv {
|
||||||
|
inherit name;
|
||||||
|
paths =
|
||||||
|
builtins.map (spec: renderPicrew {
|
||||||
|
defaults = defs;
|
||||||
|
inherit (spec) name parts;
|
||||||
|
}) specs;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
mkRenderPicrew = {
|
||||||
|
images,
|
||||||
|
ordering,
|
||||||
|
pkgs
|
||||||
|
}@args: {
|
||||||
|
name,
|
||||||
|
parts,
|
||||||
|
defaults ? {},
|
||||||
|
src ? images,
|
||||||
|
ordering ? args.ordering
|
||||||
|
}: let
|
||||||
|
|
||||||
|
compiledSpec = mergeSets defaults parts;
|
||||||
|
argList = setToFilePaths ordering compiledSpec;
|
||||||
|
imList =
|
||||||
|
if builtins.length argList <= 2 then
|
||||||
|
builtins.concatStringsSep " " argList
|
||||||
|
else
|
||||||
|
builtins.head argList + " "
|
||||||
|
+ builtins.concatStringsSep " -composite "
|
||||||
|
(builtins.tail argList);
|
||||||
|
|
||||||
|
in pkgs.stdenv.mkDerivation {
|
||||||
|
inherit name src;
|
||||||
|
buildInputs = [ pkgs.imagemagick ];
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out
|
||||||
|
convert ${imList} -composite $out/${name}.png
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
in {
|
||||||
|
inherit mkLibPicrew;
|
||||||
|
}
|
Loading…
Reference in a new issue