Free Hero Mesh

Check-in [bf1d25458b]
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 rotation and add/delete pictures commands into the picture editor. Also correct the maximum number of picture variants.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: bf1d25458b1d4040d26f698a6caab22608546f5b
User & Date: user on 2021-01-18 06:04:10
Other Links: manifest | tags
Context
2021-01-18
23:27
Add drawing ellipses into picture editor check-in: 38ac4dd10f user: user tags: trunk
06:04
Add rotation and add/delete pictures commands into the picture editor. Also correct the maximum number of picture variants. check-in: bf1d25458b user: user tags: trunk
00:46
Add documentation for picture editor check-in: 65cf966d49 user: user tags: trunk
Changes

Modified picedit.c from [8ece4cf928] to [665be25639].

75
76
77
78
79
80
81








82
83
84
85
86
87
88
  }
done:
  if(st) sqlite3_finalize(st);
  if(fp) fclose(fp);
  free(nam);
  free(buf);
  fprintf(stderr,"Done\n");








  return r;
}

static void save_picture_file(void) {
  sqlite3_stmt*st;
  FILE*fp;
  char*s=sqlite3_mprintf("%s.xclass",basefilename);







>
>
>
>
>
>
>
>







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  }
done:
  if(st) sqlite3_finalize(st);
  if(fp) fclose(fp);
  free(nam);
  free(buf);
  fprintf(stderr,"Done\n");
  sqlite3_exec(userdb,
    "CREATE TRIGGER `PICEDIT_T1` BEFORE INSERT ON `PICEDIT` BEGIN"
    "  SELECT RAISE(FAIL,'Duplicate name') FROM `PICEDIT` WHERE `NAME`=NEW.`NAME`;"
    "END;"
    "CREATE TRIGGER `PICEDIT_T2` BEFORE UPDATE OF `NAME` ON `PICEDIT` BEGIN"
    "  SELECT RAISE(FAIL,'Duplicate name') FROM `PICEDIT` WHERE `NAME`=NEW.`NAME`;"
    "END;"
  ,0,0,0);
  return r;
}

static void save_picture_file(void) {
  sqlite3_stmt*st;
  FILE*fp;
  char*s=sqlite3_mprintf("%s.xclass",basefilename);
184
185
186
187
188
189
190






















191
192
193
194
195
196
197
    if(m&2) y=s-y-1;
    *p++=d[m&4?x*s+y:y*s+x];
    if(m&1) x=s-x-1;
    if(m&2) y=s-y-1;
  }
  memcpy(d,buf,s*s);
}























static void load_picture_lump(const unsigned char*data,int len,Picture**pict) {
  Uint8 buf[32];
  FILE*fp;
  int i,j,n;
  if(!len) return;
  fp=fmemopen((unsigned char*)data,len,"r");







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







192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
    if(m&2) y=s-y-1;
    *p++=d[m&4?x*s+y:y*s+x];
    if(m&1) x=s-x-1;
    if(m&2) y=s-y-1;
  }
  memcpy(d,buf,s*s);
}

static void block_rotate(Uint8*d,Uint8 s,Uint8 w,Uint8 h,Uint8 m) {
  Uint8*b=malloc(w*h);
  Uint8*p=b;
  int x,y;
  if(!b) fatal("Allocation failed\n");
  if(w!=h && (m&4)) goto end;
  for(y=0;y<h;y++) for(x=0;x<w;x++) {
    if(m&1) x=w-x-1;
    if(m&2) y=h-y-1;
    *p++=d[m&4?x*s+y:y*s+x];
    if(m&1) x=w-x-1;
    if(m&2) y=h-y-1;
  }
  p=b;
  for(y=0;y<h;y++) {
    memcpy(d,p,w);
    p+=w;
    d+=s;
  }
  end: free(b);
}

static void load_picture_lump(const unsigned char*data,int len,Picture**pict) {
  Uint8 buf[32];
  FILE*fp;
  int i,j,n;
  if(!len) return;
  fp=fmemopen((unsigned char*)data,len,"r");
569
570
571
572
573
574
575
















576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
            }
            goto redraw;
          case SDLK_DELETE: case SDLK_KP_PERIOD:
            if(!m.w) break;
            p=pict[sel]->data+(m.y+1)*pict[sel]->size+m.x;
            for(y=0;y<m.h;y++) memset(p,0,m.w),p+=pict[sel]->size;
            goto redraw;
















          case SDLK_F5: resize:
            m.x=m.y=m.w=m.h=0; xx=yy=-1;
            p=(Uint8*)screen_prompt("Size? (1 to 255, or P to paste)");
            if(!p || !*p) goto redraw;
            if(*p=='p' || *p=='P') {
              if(!pclip || pclip->meth!=pclip->size) goto redraw;
              i=pclip->size;
            } else {
              i=strtol(p,0,10);
            }
            if(i<1 || i>255) goto redraw;
            free(pict[sel]);
            pict[sel]=malloc(sizeof(Picture)+(i+1)*i);
            if(!pict[sel]) fatal("Allocation failed\n");
            pict[sel]->size=i;
            if(*p=='p' || *p=='P') memcpy(pict[sel]->data,pclip->data,(i+1)*i);
            else memset(pict[sel]->data,0,(i+1)*i);
            goto redraw;
          case SDLK_F6:
            if(pict[15]) break;
            for(sel=0;sel<15;sel++) if(!pict[sel]) break;
            goto resize;
          case SDLK_F7:
            if(!sel && !pict[1]) break;
            free(pict[sel]);
            for(i=sel;i<15;i++) pict[i]=pict[i+1];
            pict[15]=0;







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



















|







599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
            }
            goto redraw;
          case SDLK_DELETE: case SDLK_KP_PERIOD:
            if(!m.w) break;
            p=pict[sel]->data+(m.y+1)*pict[sel]->size+m.x;
            for(y=0;y<m.h;y++) memset(p,0,m.w),p+=pict[sel]->size;
            goto redraw;
          case SDLK_F1:
            if(!m.w) m.w=m.h=pict[sel]->size;
            block_rotate(pict[sel]->data+(m.y+1)*pict[sel]->size+m.x,pict[sel]->size,m.w,m.h,5);
            goto redraw;
          case SDLK_F2:
            if(!m.w) m.w=m.h=pict[sel]->size;
            block_rotate(pict[sel]->data+(m.y+1)*pict[sel]->size+m.x,pict[sel]->size,m.w,m.h,6);
            goto redraw;
          case SDLK_F3:
            if(!m.w) m.w=m.h=pict[sel]->size;
            block_rotate(pict[sel]->data+(m.y+1)*pict[sel]->size+m.x,pict[sel]->size,m.w,m.h,2);
            goto redraw;
          case SDLK_F4:
            if(!m.w) m.w=m.h=pict[sel]->size;
            block_rotate(pict[sel]->data+(m.y+1)*pict[sel]->size+m.x,pict[sel]->size,m.w,m.h,1);
            goto redraw;
          case SDLK_F5: resize:
            m.x=m.y=m.w=m.h=0; xx=yy=-1;
            p=(Uint8*)screen_prompt("Size? (1 to 255, or P to paste)");
            if(!p || !*p) goto redraw;
            if(*p=='p' || *p=='P') {
              if(!pclip || pclip->meth!=pclip->size) goto redraw;
              i=pclip->size;
            } else {
              i=strtol(p,0,10);
            }
            if(i<1 || i>255) goto redraw;
            free(pict[sel]);
            pict[sel]=malloc(sizeof(Picture)+(i+1)*i);
            if(!pict[sel]) fatal("Allocation failed\n");
            pict[sel]->size=i;
            if(*p=='p' || *p=='P') memcpy(pict[sel]->data,pclip->data,(i+1)*i);
            else memset(pict[sel]->data,0,(i+1)*i);
            goto redraw;
          case SDLK_F6:
            if(pict[14]) break;
            for(sel=0;sel<15;sel++) if(!pict[sel]) break;
            goto resize;
          case SDLK_F7:
            if(!sel && !pict[1]) break;
            free(pict[sel]);
            for(i=sel;i<15;i++) pict[i]=pict[i+1];
            pict[15]=0;
652
653
654
655
656
657
658







































659
660
661
662
663
664
665
  free(name);
  for(i=0;i<16;i++) {
    
    free(pict[i]);
  }
  
}








































static void set_caption(void) {
  char buf[256];
  snprintf(buf,255,"Free Hero Mesh - %s - Picture",basefilename);
  SDL_WM_SetCaption(buf,buf);
}








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







698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
  free(name);
  for(i=0;i<16;i++) {
    
    free(pict[i]);
  }
  
}

static int add_picture(int t) {
  sqlite3_stmt*st;
  const char*s=screen_prompt("Enter name of new picture:");
  int i;
  if(!s || !*s) return 0;
  if(sqlite3_prepare_v2(userdb,"INSERT INTO `PICEDIT`(`NAME`,`TYPE`,`DATA`) SELECT REPLACE(?1||'.IMG','.IMG.IMG','.IMG'),1,X'';",-1,&st,0)) {
    screen_message(sqlite3_errmsg(userdb));
    return 0;
  }
  sqlite3_bind_text(st,1,s,-1,0);
  i=sqlite3_step(st);
  sqlite3_finalize(st);
  if(i!=SQLITE_DONE) {
    screen_message(sqlite3_errmsg(userdb));
    return 0;
  }
  edit_picture(sqlite3_last_insert_rowid(userdb));
  return 1;
}

static int delete_picture(void) {
  sqlite3_stmt*st;
  const char*s=screen_prompt("Enter name of picture to delete:");
  int i;
  if(!s || !*s) return 0;
  if(sqlite3_prepare_v2(userdb,"DELETE FROM `PICEDIT` WHERE `NAME`=REPLACE(?1||'.IMG','.IMG.IMG','.IMG');",-1,&st,0)) {
    screen_message(sqlite3_errmsg(userdb));
    return 0;
  }
  sqlite3_bind_text(st,1,s,-1,0);
  i=sqlite3_step(st);
  sqlite3_finalize(st);
  if(i!=SQLITE_DONE) {
    screen_message(sqlite3_errmsg(userdb));
    return 0;
  }
  return 1;
}

static void set_caption(void) {
  char buf[256];
  snprintf(buf,255,"Free Hero Mesh - %s - Picture",basefilename);
  SDL_WM_SetCaption(buf,buf);
}

717
718
719
720
721
722
723







724
725
726
727
728
729
730
            return;
          case SDLK_HOME: case SDLK_KP7: sc=0; goto redraw;
          case SDLK_UP: case SDLK_KP8: if(sc) --sc; goto redraw;
          case SDLK_DOWN: case SDLK_KP2: ++sc; goto redraw;
          case SDLK_END: case SDLK_KP1: sc=max-screen->h/8+1; goto redraw;
          case SDLK_PAGEUP: case SDLK_KP9: sc-=screen->h/8-1; goto redraw;
          case SDLK_PAGEDOWN: case SDLK_KP3: sc+=screen->h/8-1; goto redraw;







          case SDLK_F3:
            *ids=ask_picture_id("Edit:");
            if(*ids) edit_picture(*ids);
            goto redraw;
        }
        break;
      case SDL_MOUSEMOTION:







>
>
>
>
>
>
>







802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
            return;
          case SDLK_HOME: case SDLK_KP7: sc=0; goto redraw;
          case SDLK_UP: case SDLK_KP8: if(sc) --sc; goto redraw;
          case SDLK_DOWN: case SDLK_KP2: ++sc; goto redraw;
          case SDLK_END: case SDLK_KP1: sc=max-screen->h/8+1; goto redraw;
          case SDLK_PAGEUP: case SDLK_KP9: sc-=screen->h/8-1; goto redraw;
          case SDLK_PAGEDOWN: case SDLK_KP3: sc+=screen->h/8-1; goto redraw;
          case SDLK_F1:
            if(max<65535) max+=add_picture(1);
            else screen_message("Too many pictures");
            goto redraw;
          case SDLK_F2:
            max-=delete_picture();
            goto redraw;
          case SDLK_F3:
            *ids=ask_picture_id("Edit:");
            if(*ids) edit_picture(*ids);
            goto redraw;
        }
        break;
      case SDL_MOUSEMOTION:

Modified picedit.doc from [079b9d3c63] to [47704e2e89].

1
2
3
4
5
6








7
8
9
10
11
12
13
This document describes the picture editor of Free Hero Mesh.

To start the picture editor, use the -p switch. In this case, the puzzle
set files are not required to exist; the .xclass file will be created if
necessary, and the other ones are ignored.










=== Main menu ===

The main menu displays the list of the names of all pictures. This list is
sorted by name.

You can push escape to quit and save, or shift+escape quits without saving.






>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
This document describes the picture editor of Free Hero Mesh.

To start the picture editor, use the -p switch. In this case, the puzzle
set files are not required to exist; the .xclass file will be created if
necessary, and the other ones are ignored.

This allows creating the graphics for the classes of objects in the puzzle
set. The class definition file will associate one or more pictures with
each class, using the names given in the picture file.

Each named picture can have up to fifteen variants. Only one variant is
used; which one is used depends on the .altImage and .imageSize settings,
which can be defined by the end user.


=== Main menu ===

The main menu displays the list of the names of all pictures. This list is
sorted by name.

You can push escape to quit and save, or shift+escape quits without saving.
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

Arrows
  Allows selecting a colour without using the mouse.

Home
  Selects transparency as the current colour.















F5
  Resizes the current image variant. It will ask for the size; enter a
  number from 1 to 255 to set the size (which is always square), and then
  it will resize and clear the image. If you enter P then it will become
  a copy of the contents of the clipboard; this won't work if the contents
  of the clipboard is not square.

F6
  Add a new image variant. It will ask for the size, like with F5, except
  this adds a new one rather than replacing the existing one. The maximum
  number of image variants is sixteen.

F7
  Delete the current image variant. You cannot delete all of the variants
  of an image; you must have at least one.

F8 or number pad *
  Mark the entire image as a block.







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










|







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

Arrows
  Allows selecting a colour without using the mouse.

Home
  Selects transparency as the current colour.

F1
  Rotate marked area clockwise by 90 degrees. The marked area must be
  square in order for this to work.

F2
  Rotate marked area counterclockwise by 90 degrees. The marked area must
  be square in order for this to work.

F3
  Flip marked area verticaly.

F4
  Flip marked area horizontally.

F5
  Resizes the current image variant. It will ask for the size; enter a
  number from 1 to 255 to set the size (which is always square), and then
  it will resize and clear the image. If you enter P then it will become
  a copy of the contents of the clipboard; this won't work if the contents
  of the clipboard is not square.

F6
  Add a new image variant. It will ask for the size, like with F5, except
  this adds a new one rather than replacing the existing one. The maximum
  number of image variants is fifteen.

F7
  Delete the current image variant. You cannot delete all of the variants
  of an image; you must have at least one.

F8 or number pad *
  Mark the entire image as a block.