Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Command-line options and snap packaging #18

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 130 additions & 7 deletions Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,122 @@ The above copyright notice and this permission notice shall be included in all c
using System;
using System.Xml;

using NDesk.Options;

static class Program
{
static void Main()
static void Main(string[] args)
{
bool showHelp = false;
string samplesFrom = "";
string inputPath = "";
string outputFile = "out.png";

string modelName = "overlapping";
bool periodic = false;
int width = 48;
int height = 48;
int limit = 0;

int overlapN = 2;
int overlapSymmetry = 8;
int overlapGround = 0;
bool overlapPeriodicInput = true;

string tiledSubset = default(string);
bool tiledBlack = false;

var p = new OptionSet() {
{ "samples-from=", "Process samples from XML {FILE}. All other options ignored.",
v => samplesFrom = v },
{ "i|input=", "Input {PATH}: PNG image for --model=overlapping; directory containing data.xml for --model=simpletiled",
v => inputPath = v },
{ "o|output=", "Output {FILE}, default=" + $"{outputFile}",
v => outputFile = v },
{ "w|width=", "Tiled image width {INT} when --model=simpletiled, default=" + $"{width}",
(int v) => width = v },
{ "h|height=", "Tiled image height {INT} when --model=simpletiled, default=" + $"{height}",
(int v) => height = v },
{ "m|model=", "Model {TYPE}: `overlapping` (default) or `simpletiled`. Required.",
v => modelName = v },
{ "n=", "{N} parameter, when --model=overlapping, default=" + $"{overlapN}",
(int v) => overlapN = v },
{ "limit=", "Model limit {INT}, default="+ $"{limit}",
(int v) => limit = v },
{ "p|periodic", "Periodic, default false",
v => periodic = v != null },
{ "symmetry=", "Symmetry {INT}, when --model=overlapping, default=" + $"{overlapSymmetry}",
(int v) => overlapSymmetry = v },
{ "ground=", "Ground {INT}, when --model=overlapping, default=" + $"{overlapGround}",
(int v) => overlapGround = v },
{ "pi|periodicInput=", "Periodic input {BOOL}, when --model=overlapping, default=" + $"{overlapPeriodicInput}",
(bool v) => overlapPeriodicInput = v },
{ "subset=", "Subset {NAME} in data.xml, when --model=simpletiled",
v => tiledSubset = v },
{ "black=", "Black, when --model=simpletiled, default false",
v => tiledBlack = v != null },
{ "help", "Display help and exit",
v => showHelp = v != null },
};
try {
p.Parse(args);
}
catch (OptionException e) {
Console.Write("wfc: ");
Console.Write(e.Message);
Console.WriteLine("Try `wfc --help` for more information.");
return;
}

if (showHelp) {
ShowHelp(p);
return;
}

if (samplesFrom != "") {
processSamplesFrom(samplesFrom);
return;
}

if (inputPath == "") {
Console.WriteLine("wfc: missing input");
ShowHelp(p);
return;
}

Random random = new Random();
Model model;

if (modelName == "overlapping") {
model = new OverlappingModel(
inputPath, overlapN, width, height, overlapPeriodicInput, periodic, overlapSymmetry, overlapGround);
} else if (modelName == "simpletiled") {
model = new SimpleTiledModel(
inputPath, tiledSubset, width, height, periodic, tiledBlack);
} else {
Console.WriteLine("wfc: unsupported model type: " + modelName);
ShowHelp(p);
return;
}

for (int k = 0; k < 10; k++)
{
int seed = random.Next();
bool finished = model.Run(seed, limit);
if (finished)
{
Console.WriteLine("DONE");
model.Graphics().Save($"{outputFile}");
break;
}
else Console.WriteLine("CONTRADICTION");
}
}

static void processSamplesFrom(string samplesFrom) {
Random random = new Random();
var xdoc = new XmlDocument();
xdoc.Load("samples.xml");
xdoc.Load(samplesFrom);

int counter = 1;
foreach (XmlNode xnode in xdoc.FirstChild.ChildNodes)
Expand All @@ -26,11 +135,16 @@ static void Main()
string name = xnode.Get<string>("name");
Console.WriteLine($"< {name}");

if (xnode.Name == "overlapping") model = new OverlappingModel(name, xnode.Get("N", 2), xnode.Get("width", 48), xnode.Get("height", 48),
xnode.Get("periodicInput", true), xnode.Get("periodic", false), xnode.Get("symmetry", 8), xnode.Get("ground", 0));
else if (xnode.Name == "simpletiled") model = new SimpleTiledModel(name, xnode.Get<string>("subset"),
xnode.Get("width", 10), xnode.Get("height", 10), xnode.Get("periodic", false), xnode.Get("black", false));
else continue;
if (xnode.Name == "overlapping") {
string inputPath = $"samples/{name}.png";
model = new OverlappingModel(inputPath, xnode.Get("N", 2), xnode.Get("width", 48), xnode.Get("height", 48),
xnode.Get("periodicInput", true), xnode.Get("periodic", false),
xnode.Get("symmetry", 8), xnode.Get("foundation", 0));
} else if (xnode.Name == "simpletiled") {
string inputPath = $"samples/{name}";
model = new SimpleTiledModel(inputPath, xnode.Get<string>("subset"),
xnode.Get("width", 10), xnode.Get("height", 10), xnode.Get("periodic", false), xnode.Get("black", false));
} else continue;

for (int i = 0; i < xnode.Get("screenshots", 2); i++)
{
Expand All @@ -52,4 +166,13 @@ static void Main()
counter++;
}
}

static void ShowHelp (OptionSet p)
{
Console.WriteLine ("Usage: wfc [OPTIONS]");
Console.WriteLine ("Bitmap & tilemap generation from a single example with the help of ideas from quantum mechanics.");
Console.WriteLine ();
Console.WriteLine ("Options:");
p.WriteOptionDescriptions (Console.Out);
}
}
19 changes: 19 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

CSC=mcs

.PHONY: all
all: wfc.exe

install: wfc.exe
cp wfc.exe $(DESTDIR)/wfc.exe

wfc.exe: Options.cs
$(CSC) /debug /d:NDESK_OPTIONS /reference:System.Drawing.dll *.cs /out:$@

Options.cs:
cp `pkg-config --variable=Sources mono-options` .

.PHONY: clean
clean:
$(RM) wfc.exe Options.cs

4 changes: 2 additions & 2 deletions OverlappingModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ class OverlappingModel : Model
List<Color> colors;
int ground;

public OverlappingModel(string name, int N, int width, int height, bool periodicInput, bool periodicOutput, int symmetry, int ground)
public OverlappingModel(string inputPath, int N, int width, int height, bool periodicInput, bool periodicOutput, int symmetry, int ground)
{
this.N = N;
FMX = width;
FMY = height;
periodic = periodicOutput;

var bitmap = new Bitmap($"samples/{name}.png");
var bitmap = new Bitmap(inputPath);
int SMX = bitmap.Width, SMY = bitmap.Height;
byte[,] sample = new byte[SMX, SMY];
colors = new List<Color>();
Expand Down
8 changes: 4 additions & 4 deletions SimpleTiledModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ class SimpleTiledModel : Model
int tilesize;
bool black;

public SimpleTiledModel(string name, string subsetName, int width, int height, bool periodic, bool black)
public SimpleTiledModel(string inputPath, string subsetName, int width, int height, bool periodic, bool black)
{
FMX = width;
FMY = height;
this.periodic = periodic;
this.black = black;

var xdoc = new XmlDocument();
xdoc.Load($"samples/{name}/data.xml");
xdoc.Load($"{inputPath}/data.xml");
XmlNode xnode = xdoc.FirstChild;
tilesize = xnode.Get("size", 16);
bool unique = xnode.Get("unique", false);
Expand Down Expand Up @@ -124,13 +124,13 @@ public SimpleTiledModel(string name, string subsetName, int width, int height, b
{
for (int t = 0; t < cardinality; t++)
{
Bitmap bitmap = new Bitmap($"samples/{name}/{tilename} {t}.png");
Bitmap bitmap = new Bitmap($"{inputPath}/{tilename} {t}.png");
tiles.Add(tile((x, y) => bitmap.GetPixel(x, y)));
}
}
else
{
Bitmap bitmap = new Bitmap($"samples/{name}/{tilename}.png");
Bitmap bitmap = new Bitmap($"{inputPath}/{tilename}.png");
tiles.Add(tile((x, y) => bitmap.GetPixel(x, y)));
for (int t = 1; t < cardinality; t++) tiles.Add(rotate(tiles[T + t - 1]));
}
Expand Down
30 changes: 30 additions & 0 deletions snapcraft.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: wfc
version: 0
summary: This program generates bitmaps that are locally similar to the input bitmap.
description: |
Bitmap & tilemap generation from a single example with the help of ideas from
quantum mechanics.

grade: stable # must be 'stable' to release into candidate/stable channels
confinement: strict # use 'strict' once you have the right plugs and slots

apps:
wfc:
command: wfc-wrapper
plugs:
- home

parts:
build-wfc:
plugin: make
source: .
build-packages: [mono-devel]
stage-packages: [mono-runtime, libmono-system-core4.0-cil, libmono-system-drawing4.0-cil]
copy-wfc:
plugin: dump
source: .
snap:
- wfc-wrapper
- wfc.exe
- usr/lib/mono/*/*
- usr/bin/mono
11 changes: 11 additions & 0 deletions wfc-wrapper
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash -e

export MONO_PATH=${SNAP}/usr/lib/mono/4.5
export HOME=${SNAP_USER_DATA}

if [ ! -e "${HOME}/.mono/config" ]; then
mkdir -p ${HOME}/.mono
cp ${SNAP}/etc/mono/config ${HOME}/.mono/config
fi

exec ${SNAP}/usr/bin/mono ${SNAP}/wfc.exe "$@"