Free Hero Mesh

Check-in [7e6d0f4f80]
Login
This is a mirror of the main repository for Free Hero Mesh. New tickets and changes will not be accepted at this mirror.
Overview
Comment:Add the possibility to use SQL queries in the picture editor.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 7e6d0f4f80c22e9c96928403cf4111f736051f56
User & Date: user on 2021-05-05 02:33:08
Other Links: manifest | tags
Context
2021-05-05
20:03
Add the possibility to edit Misc/Dir of existing objects. check-in: acca5b95d3 user: user tags: trunk
02:33
Add the possibility to use SQL queries in the picture editor. check-in: 7e6d0f4f80 user: user tags: trunk
2021-05-02
20:13
When adding a new object to the MRU list, ensure that it is selected as the current MRU. check-in: aaae541d8a user: user tags: trunk
Changes

Modified picedit.c from [1befa9e779] to [8c2ed17c26].

52
53
54
55
56
57
58





59
60
61

62
63
64
65
66
67
68
69
70












































































71
72
73
74
75
76
77
} Filter;

typedef struct {
  char basename[64];
  Filter filters[64];
  Uint8 nfilters;
} DependentPicture;






static Uint8 cur_type;
static Uint8 gsizes[16];


static void fn_valid_name(sqlite3_context*cxt,int argc,sqlite3_value**argv) {
  const char*s=sqlite3_value_text(*argv);
  if(!s || !*s || s[strspn(s,"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-0123456789")]) {
    sqlite3_result_error(cxt,"Invalid name",-1);
    return;
  }
  sqlite3_result_value(cxt,*argv);
}













































































static int load_picture_file(void) {
  sqlite3_stmt*st=0;
  FILE*fp;
  char*nam;
  char*buf=0;
  int r=0;







>
>
>
>
>



>









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
} Filter;

typedef struct {
  char basename[64];
  Filter filters[64];
  Uint8 nfilters;
} DependentPicture;

typedef struct {
  sqlite3_vtab_cursor super;
  int pos;
} Cursor;

static Uint8 cur_type;
static Uint8 gsizes[16];
static Picture*cur_pic;

static void fn_valid_name(sqlite3_context*cxt,int argc,sqlite3_value**argv) {
  const char*s=sqlite3_value_text(*argv);
  if(!s || !*s || s[strspn(s,"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-0123456789")]) {
    sqlite3_result_error(cxt,"Invalid name",-1);
    return;
  }
  sqlite3_result_value(cxt,*argv);
}

static int vt_graph_close(sqlite3_vtab_cursor*cur) {
  sqlite3_free(cur);
  return SQLITE_OK;
}

static int vt_graph_eof(sqlite3_vtab_cursor*cc) {
  Cursor*cur=(void*)cc;
  return (!cur_pic || cur->pos>=cur_pic->size*cur_pic->size);
}

static int vt_graph_open(sqlite3_vtab*vt,sqlite3_vtab_cursor**cur) {
  *cur=sqlite3_malloc(sizeof(Cursor));
  return *cur?SQLITE_OK:SQLITE_NOMEM;
}

static int vt_graph_connect(sqlite3*db,void*aux,int argc,const char*const*argv,sqlite3_vtab**vt,char**ex) {
  *vt=sqlite3_malloc(sizeof(sqlite3_vtab));
  if(!*vt) return SQLITE_NOMEM;
  sqlite3_declare_vtab(db,"CREATE TABLE `GRID`(`X` INT, `Y` INT, `C` INT);");
  return SQLITE_OK;
}

static int vt_graph_disconnect(sqlite3_vtab*vt) {
  sqlite3_free(vt);
  return SQLITE_OK;
}

static int vt_graph_filter(sqlite3_vtab_cursor*cc,int n,const char*s,int c,sqlite3_value**v) {
  Cursor*cur=(void*)cc;
  cur->pos=0;
  return SQLITE_OK;
}

static int vt_graph_index(sqlite3_vtab*vt,sqlite3_index_info*inf) {
  return SQLITE_OK;
}

static int vt_graph_column(sqlite3_vtab_cursor*cc,sqlite3_context*cxt,int n) {
  Cursor*cur=(void*)cc;
  sqlite3_result_int(cxt,n==0?cur->pos%cur_pic->size:n==1?cur->pos/cur_pic->size:cur_pic->data[cur->pos+cur_pic->size]);
  return SQLITE_OK;
}

static int vt_graph_next(sqlite3_vtab_cursor*cc) {
  Cursor*cur=(void*)cc;
  cur->pos++;
  return SQLITE_OK;
}

static int vt_graph_rowid(sqlite3_vtab_cursor*cc,sqlite3_int64*p) {
  Cursor*cur=(void*)cc;
  *p=cur->pos;
  return SQLITE_OK;
}

static int vt_graph_update(sqlite3_vtab*vt,int argc,sqlite3_value**argv,sqlite3_int64*rowid) {
  if(argc!=5 || sqlite3_value_type(argv[0])==SQLITE_NULL) return SQLITE_ERROR;
  cur_pic->data[cur_pic->size+sqlite3_value_int(argv[0])]=sqlite3_value_int(argv[4]);
  return SQLITE_OK;
}

static const sqlite3_module vt_graph={
  .iVersion=1,
  .xBestIndex=vt_graph_index,
  .xClose=vt_graph_close,
  .xColumn=vt_graph_column,
  .xConnect=vt_graph_connect,
  .xDisconnect=vt_graph_disconnect,
  .xEof=vt_graph_eof,
  .xFilter=vt_graph_filter,
  .xNext=vt_graph_next,
  .xOpen=vt_graph_open,
  .xRowid=vt_graph_rowid,
  .xUpdate=vt_graph_update,
};

static int load_picture_file(void) {
  sqlite3_stmt*st=0;
  FILE*fp;
  char*nam;
  char*buf=0;
  int r=0;
516
517
518
519
520
521
522





523
524
525
526
527
528
529
    fputc(pal[c].r,fp); fputc(pal[c].r,fp);
    fputc(pal[c].g,fp); fputc(pal[c].g,fp);
    fputc(pal[c].b,fp); fputc(pal[c].b,fp);
    fputc(c?255:0,fp); fputc(c?255:0,fp);
  }
  pclose(fp);
}






static inline void edit_picture_1(Picture**pict,const char*name) {
  static const Uint8 shade[64]=
    "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
    "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
    "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
    "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"







>
>
>
>
>







598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
    fputc(pal[c].r,fp); fputc(pal[c].r,fp);
    fputc(pal[c].g,fp); fputc(pal[c].g,fp);
    fputc(pal[c].b,fp); fputc(pal[c].b,fp);
    fputc(c?255:0,fp); fputc(c?255:0,fp);
  }
  pclose(fp);
}

static int response_cb(void*aux,int argc,char**argv,char**names) {
  if(argc && *argv) screen_message(*argv);
  return 1;
}

static inline void edit_picture_1(Picture**pict,const char*name) {
  static const Uint8 shade[64]=
    "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
    "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
    "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
    "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
556
557
558
559
560
561
562

563
564
565
566
567
568
569
  int xx=-1;
  int yy=-1;
  unsigned char buf[256];
  m.x=m.y=m.w=m.h=0;
  set_cursor(XC_arrow);
  redraw:
  if((sel&~15) || !pict[sel]) sel=0;

  z=screen->w-pict[sel]->size-169;
  if(z>screen->h-49) z=screen->h-49;
  z/=pict[sel]->size;
  if(z<3) return;
  if(z>32) z=32;
  SDL_LockSurface(screen);
  p=screen->pixels;







>







643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
  int xx=-1;
  int yy=-1;
  unsigned char buf[256];
  m.x=m.y=m.w=m.h=0;
  set_cursor(XC_arrow);
  redraw:
  if((sel&~15) || !pict[sel]) sel=0;
  cur_pic=pict[sel];
  z=screen->w-pict[sel]->size-169;
  if(z>screen->h-49) z=screen->h-49;
  z/=pict[sel]->size;
  if(z<3) return;
  if(z>32) z=32;
  SDL_LockSurface(screen);
  p=screen->pixels;
900
901
902
903
904
905
906




907
908
909
910
911
912
913
            do_export(pict[sel]);
            goto redraw;
          case SDLK_LEFT: case SDLK_KP4: --cc; goto redraw;
          case SDLK_RIGHT: case SDLK_KP6: ++cc; goto redraw;
          case SDLK_UP: case SDLK_KP8: cc-=16; goto redraw;
          case SDLK_DOWN: case SDLK_KP2: cc+=16; goto redraw;
          case SDLK_HOME: case SDLK_KP7: cc=0; goto redraw;




        }
        break;
      case SDL_VIDEOEXPOSE:
        goto redraw;
    }
  }
}







>
>
>
>







988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
            do_export(pict[sel]);
            goto redraw;
          case SDLK_LEFT: case SDLK_KP4: --cc; goto redraw;
          case SDLK_RIGHT: case SDLK_KP6: ++cc; goto redraw;
          case SDLK_UP: case SDLK_KP8: cc-=16; goto redraw;
          case SDLK_DOWN: case SDLK_KP2: cc+=16; goto redraw;
          case SDLK_HOME: case SDLK_KP7: cc=0; goto redraw;
          case SDLK_F12:
            p=(Uint8*)screen_prompt("<SQL>");
            if(p) sqlite3_exec(userdb,p,response_cb,0,0);
            goto redraw;
        }
        break;
      case SDL_VIDEOEXPOSE:
        goto redraw;
    }
  }
}
1301
1302
1303
1304
1305
1306
1307

1308
1309
1310
1311
1312
1313
1314
        pict[i]=malloc(sizeof(Picture)+(gsizes[i]+1)*gsizes[i]);
        if(!pict[i]) fatal("Allocation failed\n");
        pict[i]->size=gsizes[i];
        memset(pict[i]->data,0,(gsizes[i]+1)*gsizes[i]);
      }
    }
    edit_picture_1(pict,name);

    fp=open_memstream((char**)&buf,&size);
    if(!fp) fatal("Cannot open memory stream\n");
    for(i=n=0;i<16;i++) if(pict[i]) n++;
    fputc(n,fp);
    for(i=0;i<n;i++) fputc(pict[i]->size,fp);
    for(i=0;i<n>>1;i++) fputc(0,fp);
    for(i=0;i<n;i++) compress_picture(fp,pict[i]);







>







1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
        pict[i]=malloc(sizeof(Picture)+(gsizes[i]+1)*gsizes[i]);
        if(!pict[i]) fatal("Allocation failed\n");
        pict[i]->size=gsizes[i];
        memset(pict[i]->data,0,(gsizes[i]+1)*gsizes[i]);
      }
    }
    edit_picture_1(pict,name);
    cur_pic=0;
    fp=open_memstream((char**)&buf,&size);
    if(!fp) fatal("Cannot open memory stream\n");
    for(i=n=0;i<16;i++) if(pict[i]) n++;
    fputc(n,fp);
    for(i=0;i<n;i++) fputc(pict[i]->size,fp);
    for(i=0;i<n>>1;i++) fputc(0,fp);
    for(i=0;i<n;i++) compress_picture(fp,pict[i]);
1438
1439
1440
1441
1442
1443
1444

1445
1446
1447
1448
1449
1450
1451
  SDL_Event ev;
  SDL_Rect r;
  sqlite3_stmt*st;
  int sc=0;
  int max=load_picture_file();
  int i,n;
  sqlite3_create_function(userdb,"VALID_NAME",1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_valid_name,0,0);

  init_palette();
  optionquery[1]=Q_imageSize;
  *gsizes=picture_size=strtol(xrm_get_resource(resourcedb,optionquery,optionquery,2)?:"16",0,10);
  set_cursor(XC_arrow);
  set_caption();
  i=sqlite3_prepare_v3(userdb,"SELECT `ID`,SUBSTR(`NAME`,1,LENGTH(`NAME`)-4),`TYPE` FROM `PICEDIT` WHERE `TYPE` ORDER BY `NAME` LIMIT ?1 OFFSET ?2;",-1,SQLITE_PREPARE_PERSISTENT,&st,0);
  if(i) fatal("SQL error (%d): %s\n",i,sqlite3_errmsg(userdb));







>







1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
  SDL_Event ev;
  SDL_Rect r;
  sqlite3_stmt*st;
  int sc=0;
  int max=load_picture_file();
  int i,n;
  sqlite3_create_function(userdb,"VALID_NAME",1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_valid_name,0,0);
  sqlite3_create_module(userdb,"GRAPH",&vt_graph,0);
  init_palette();
  optionquery[1]=Q_imageSize;
  *gsizes=picture_size=strtol(xrm_get_resource(resourcedb,optionquery,optionquery,2)?:"16",0,10);
  set_cursor(XC_arrow);
  set_caption();
  i=sqlite3_prepare_v3(userdb,"SELECT `ID`,SUBSTR(`NAME`,1,LENGTH(`NAME`)-4),`TYPE` FROM `PICEDIT` WHERE `TYPE` ORDER BY `NAME` LIMIT ?1 OFFSET ?2;",-1,SQLITE_PREPARE_PERSISTENT,&st,0);
  if(i) fatal("SQL error (%d): %s\n",i,sqlite3_errmsg(userdb));

Modified picedit.doc from [daa21e621e] to [87de92095b].

117
118
119
120
121
122
123








124
125
126
127
128
129
130
  will produce a square farbfeld picture on stdout. The imported picture
  will replace the current picture variant.

F10
  Export a picture. At the prompt, you must enter a system command which
  will read a farbfeld picture from stdin.









Click in the colour palette on the right to select a colour. With the left
button, that colour is selected as the current colour. The middle button
will replace everything of the current colour with the clicked colour, and
the right button will exchange pixels between the current colour and the
clicked colour; in either case, if any block is marked, only the marked
block will be affected.








>
>
>
>
>
>
>
>







117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
  will produce a square farbfeld picture on stdout. The imported picture
  will replace the current picture variant.

F10
  Export a picture. At the prompt, you must enter a system command which
  will read a farbfeld picture from stdin.

F12
  Enter a SQL statement to edit the current picture. This should be a
  UPDATE statement which updates the column called "C" of the table called
  "GRAPH". It has columns "X" and "Y" which are the coordinates of the
  pixel, and "C" which is the colour of the pixel. It may also be a SELECT
  statement in order to query it, and the response is then displayed
  (which must be a single row and single column only).

Click in the colour palette on the right to select a colour. With the left
button, that colour is selected as the current colour. The middle button
will replace everything of the current colour with the clicked colour, and
the right button will exchange pixels between the current colour and the
clicked colour; in either case, if any block is marked, only the marked
block will be affected.