~l3kn/quad

10a66fd34bc990750cd1961212e21b39eb1182da — Leon Rische 6 months ago ccf407b
Configurable rule / pattern number
1 files changed, 55 insertions(+), 170 deletions(-)

M quad.c
M quad.c => quad.c +55 -170
@@ 6,24 6,10 @@

#include <SDL2/SDL.h>

#include "config.h"
#include "quad.h"
#include "patterns.h"

int width, height, menu_size, menu_width;
int size;
double zoomFactor = 1.0;
int currentRule = 0;

#define PADDING 20
#define SCALE 2
#define CANVAS_X PADDING + menu_width + menu_size
#define CANVAS_Y PADDING

#define NRULES 4
// Width of rules menu
#define WRULES 1

#define COLOR_BLACK 0x000000
#define COLOR_WHITE 0xFFFFFF
#include "menu.h"

SDL_Window* window = NULL;
SDL_Renderer* mainRenderer = NULL;


@@ 32,22 18,11 @@ SDL_Surface* grammarSurface = NULL;
SDL_Renderer* grammarRenderer = NULL;
SDL_Texture* grammarTexture = NULL;

typedef enum {
  RULE, PATTERN,
} nodeType;

typedef struct node {
  nodeType type;
  int index;
} Node;

typedef struct rule {
  Node quads[4];
  Node fallback;
} Rule;
double zoomFactor = 1.0;
int currentRule = 0;

Node selection;
Rule rules[8];
Rule rules[NRULES];
int colors[2] = { COLOR_BLACK, COLOR_WHITE };

bool outline = true;


@@ 55,32 30,6 @@ bool quit = false;
bool zooming = false;
int limit = 1;

void drawSquare(SDL_Renderer* renderer, int x, int y, int s, unsigned long long pattern) {
    SDL_Rect rect;
    rect.x = x;
    rect.y = y;
    // Offset by 1 so outlines overlap
    rect.w = s + 1;
    rect.h = s + 1;
  if (outline) {
    SDL_RenderDrawRect(renderer, &rect);
  }

  // TODO: Speed this up with memcopy on surface?
  /* if (pattern) { */
  /*   SDL_RenderFillRect(renderer, &rect); */
  /* } */
  unsigned long long index;
  for (int px = x; px < x + s; ++px) {
    for (int py = y; py < y + s; ++py) {
      index = ((px / SCALE) % 8) * 8 + ((py / SCALE) % 8);
      if ((pattern & (1UL << index)) > 0) {
        SDL_RenderDrawPoint(renderer, px, py);
      }
    }
  }
}

void expandRule(SDL_Renderer* renderer, int x, int y, int s, Rule* rule);
void expandNode(SDL_Renderer* renderer, int x, int y, int s, Node node) {
  if (node.type == RULE) {


@@ 113,57 62,6 @@ void saveBMP() {
  SDL_FreeSurface(surface);
}

void drawNumber(int x, int y, int n) {
  int h = menu_size / 2;
  int o = menu_size / 8;
  Pattern pattern = (n >= 4) ? BLACK : WHITE;

  if (n & 2) {
    y += h;
  }
  if (n & 1) {
    x += h;
  }

  drawSquare(mainRenderer, x + o, y + o, h / 2, pattern);
}

void drawNode(int x, int y, Node node) {
  if (node.type == RULE) {
    drawSquare(mainRenderer, x, y, menu_size, BLACK);
    drawNumber(x, y, node.index);
  } else {
    drawSquare(mainRenderer, x, y, menu_size, patterns[node.index]);
  }
}

void drawRule(int x, int y, int n) {
  drawNumber(x, y, n);
  Rule rule = rules[n];

  drawNode(x, y + menu_size, rule.fallback);

  drawNode(x + 2 * menu_size, y, rule.quads[0]);
  drawNode(x + 3 * menu_size, y, rule.quads[1]);
  drawNode(x + 2 * menu_size, y + menu_size, rule.quads[2]);
  drawNode(x + 3 * menu_size, y + menu_size, rule.quads[3]);
}

void drawMenu() {
  for (int i = 0; i < 10; ++i) {
    int x = i * menu_size + PADDING;
    for (int j = 0; j < 4; j ++) {
      int y = j * menu_size + PADDING;
      drawSquare(mainRenderer, x, y, menu_size, patterns[i + 10 * j]);
    }
  }

  for (int i = 0; i < NRULES; ++i) {
    drawRule(PADDING + (i % WRULES) * 6 * menu_size,
             (5 + 3 * (i / WRULES)) * menu_size + PADDING, i);
  }
}

void setColor(SDL_Renderer* renderer, int color, int alpha) {
  int r = color >> 16;
  int g = (color >> 8) & 255;


@@ 178,7 76,7 @@ void renderRule(SDL_Renderer* renderer) {
  setColor(renderer, colors[1], 17);
  setColor(grammarRenderer, colors[1], 17);

  expandRule(renderer, 0, 0, size, &rules[currentRule]);
  expandRule(renderer, 0, 0, SIZE, &rules[currentRule]);
  grammarTexture = SDL_CreateTextureFromSurface(mainRenderer, grammarSurface);
}



@@ 187,19 85,19 @@ void draw() {
  SDL_RenderClear(mainRenderer);
  setColor(mainRenderer, colors[1], SDL_ALPHA_OPAQUE);

  drawMenu();
  drawSquare(mainRenderer, CANVAS_X-1, CANVAS_Y-1, size+1, BLACK);
  drawSquare(mainRenderer, CANVAS_X-1, CANVAS_Y-1, SIZE+1, BLACK);
  drawMenu(mainRenderer, &patterns, &rules);

  SDL_Rect src, target;
  src.x = 0;
  src.y = 0;
  src.w = size / zoomFactor;
  src.h = size / zoomFactor;
  src.w = SIZE / zoomFactor;
  src.h = SIZE / zoomFactor;

  target.x = CANVAS_X;
  target.y = CANVAS_Y;
  target.w = size;
  target.h = size;
  target.w = SIZE;
  target.h = SIZE;

  SDL_RenderCopy(mainRenderer, grammarTexture, &src, &target);



@@ 268,7 166,7 @@ void handleKey(SDL_Event* event) {
    draw();
    break;
  case SDLK_d: {
    if (limit < size / 2) {
    if (limit < SIZE / 2) {
      limit <<= 1;
      renderRule(grammarRenderer);
      draw();


@@ 328,74 226,61 @@ void handleKey(SDL_Event* event) {
}

void handleMouse(SDL_Event* event) {
  int tx = (event->motion.x - PADDING) / menu_size;
  int ty = (event->motion.y - PADDING) / menu_size;

  if (tx >= 0 && tx < 10) {
    if (ty >= 0 && ty < 4) {
      selection.type = PATTERN;
      selection.index = tx + (10 * ty);
    } else if (ty >= 5 && ty < 16) {
      ty -= 5;

      int rule = 2 * (ty / 3);
      ty %= 3;
      if (tx >= 6) {
        tx -= 6;
        rule += 1;
      }

      if (tx == 0 && ty == 0) {
        selection.type = RULE;
        selection.index = rule;
      } else if (tx == 0 && ty == 1 && selection.type == PATTERN) {
        rules[rule].fallback = selection;
        renderRule(grammarRenderer);
        draw();
      } else if (tx == 2 && ty == 0) {
        rules[rule].quads[0] = selection;
        renderRule(grammarRenderer);
        draw();
      } else if (tx == 3 && ty == 0) {
        rules[rule].quads[1] = selection;
        renderRule(grammarRenderer);
        draw();
      } else if (tx == 2 && ty == 1) {
        rules[rule].quads[2] = selection;
        renderRule(grammarRenderer);
        draw();
      } else if (tx == 3 && ty == 1) {
        rules[rule].quads[3] = selection;
        renderRule(grammarRenderer);
        draw();
      }
  int tx = (event->motion.x - PADDING) / TILE_SIZE;
  int ty = (event->motion.y - PADDING) / TILE_SIZE;

  if (tx >= 0 && tx < NPATTERNS && \
      ty >= 0 && ty < HPATTERNS) {
    selection.type = PATTERN;
    selection.index = tx + (10 * ty);
  } else if (tx >= 0 && tx < MENU_WIDTH && \
             ty >= (HPATTERNS + 1) && ty < MENU_HEIGHT) {
    ty -= (HPATTERNS + 1);

    int rule = WRULES * (ty / 3) + (tx / 6);
    int rx = tx % 6;
    int ry = ty % 3;
    printf("%d,%d\n", rx, ry);

    if (rx == 0 && ry == 0) {
      selection.type = RULE;
      selection.index = rule;
    } else if (rx == 0 && ry == 1 && selection.type == PATTERN) {
      rules[rule].fallback = selection;
      renderRule(grammarRenderer);
      draw();
    } else if (rx == 2 && ry == 0) {
      rules[rule].quads[0] = selection;
      renderRule(grammarRenderer);
      draw();
    } else if (rx == 3 && ry == 0) {
      rules[rule].quads[1] = selection;
      renderRule(grammarRenderer);
      draw();
    } else if (rx == 2 && ry == 1) {
      rules[rule].quads[2] = selection;
      renderRule(grammarRenderer);
      draw();
    } else if (rx == 3 && ry == 1) {
      rules[rule].quads[3] = selection;
      renderRule(grammarRenderer);
      draw();
    }
  }
}

int main(int argc, char* argv[]) {
  size = 1024;
  if (argc == 2) {
    size = atoi(argv[1]);
  }

  if (SDL_Init(SDL_INIT_VIDEO) != 0) {
    printf("error initializing SDL: %s\n", SDL_GetError());
    return 1;
  }

  menu_size = size / 16;
  menu_width = menu_size * 10;
  width = menu_width + menu_size + size + 2 * PADDING;
  height = size + 2 * PADDING;

  if (SDL_CreateWindowAndRenderer(width, height, 0, &window, &mainRenderer) != 0) {
  if (SDL_CreateWindowAndRenderer(WIDTH, HEIGHT, 0, &window, &mainRenderer) != 0) {
    printf("Error creating window & renderer: %s\n", SDL_GetError());
    return 1;
  }


  /* grammarSurface = SDL_CreateRGBSurface(0, size, size, 32, 0, 0, 0, 0); */
  /* grammarSurface = SDL_CreateRGBSurface(0, SIZE, SIZE, 32, 0, 0, 0, 0); */
  grammarSurface = SDL_GetWindowSurface(window);
  if (grammarSurface == NULL) {
    SDL_Log("SDL_CreateRGBSurface() failed: %s", SDL_GetError());