29 if(v == nil) sysfatal("malloc: %r");
31 setmalloctag(v, getcallerpc(&sz));
38 return allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, c);
49 for(; t != nil; t = va_arg(va, ObjT *)){
51 o->tab->move(o, 0, 0, 0);
53 o->tab->move(o, trayw + Dx(o->bbox)/2, TrayH/2, 0);
65 for(o = trayo.next; o != &trayo; o = o->next)
66 o->tab->draw(o, tray);
72 grey = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
73 scr = allocscreen(screen, display->white, 0);
74 work = allocwindow(scr, Rect(screen->r.min.x, screen->r.min.y, screen->r.max.x, screen->r.max.y - TrayH), 0, 0xFFFFFFFF);
75 tray = allocwindow(scr, Rect(screen->r.min.x, screen->r.max.y - TrayH, screen->r.max.x, screen->r.max.y), 0, 0xCCCCCCFF);
79 objclick(Point p, Obj *l)
83 for(o = l->next; o != l; o = o->next)
84 if(ptinrect(p, o->bbox))
94 draw(work, work->r, display->white, nil, ZP);
95 for(o = worko.next; o != &worko; o = o->next)
96 o->tab->draw(o, work);
97 if(carry != nil && showcarry)
98 carry->tab->draw(carry, work);
99 flushimage(display, 1);
107 draw(work, work->r, display->white, nil, ZP);
108 for(o = runo.next; o != &runo; o = o->next)
109 o->tab->draw(o, work);
110 flushimage(display, 1);
114 canhinge(Obj *a, Obj *b)
118 if(a->hinge == nil || b->hinge == nil) return 0;
119 for(h = a->hinge; h != nil; h = h->onext)
120 for(k = b->hinge; k != nil; k = k->onext)
121 if(vecdist(h->p, k->p) <= HingeSep)
127 hinge(Obj *a, Obj *b)
131 if(a->hinge == nil || b->hinge == nil) return 0;
132 for(h = a->hinge; h != nil; h = h->onext)
133 for(k = b->hinge; k != nil; k = k->onext)
134 if(vecdist(h->p, k->p) <= HingeSep){
140 b->tab->move(b, b->p.x + h->p.x - k->p.x, b->p.y + h->p.y - k->p.y, b->θ);
153 for(o = worko.next; o != &worko; o = o->next)
154 if(objcoll(o, carry))
155 if(canhinge(o, carry))
159 for(o = worko.next; hinges > 0 && o != &worko; o = o->next)
160 if(objcoll(o, carry))
161 hinges -= hinge(o, carry);
162 if(hinges != 0) print("hinge error\n");
163 objcat(&worko, carry);
171 static int lbut = -1;
176 if(ptinrect(mc->xy, work->r)){
177 p = subpt(mc->xy, work->r.min);
178 if(carry != nil && (carry->p.x != p.x || carry->p.y != p.y || !showcarry)){
179 carry->tab->move(carry, p.x, p.y, carry->θ);
188 if((~mc->buttons & lbut & 1) != 0){
189 if(ptinrect(mc->xy, tray->r)){
190 carry = objclick(subpt(mc->xy, tray->r.min), &trayo);
192 carry = objdup(carry);
193 }else if(ptinrect(mc->xy, work->r)){
197 carry = objclick(subpt(mc->xy, work->r.min), &worko);
203 if((~mc->buttons & lbut & 4) != 0){
209 }else if(ptinrect(mc->xy, work->r)){
210 carry = objclick(subpt(mc->xy, work->r.min), &worko);
212 carry = objdup(carry);
223 static Cursor cursor;
225 for(o = runo.next; o != &runo; o = oo){
229 for(o = worko.next; o != &worko; o = o->next)
230 objcat(&runo, objdup(o));
231 copyhinges(&worko, &runo);
232 setcursor(mc, &cursor);
235 {mc->c, &mc->Mouse, CHANRCV},
236 {kc->c, &r, CHANRCV},
237 {nil, nil, CHANNOBLK}
241 case 0: mouse(); break;
245 case Kdel: threadexitsall(nil);
265 carry->tab->move(carry, carry->p.x, carry->p.y, carry->θ - 15);
271 carry->tab->move(carry, carry->p.x, carry->p.y, carry->θ + 15);
284 fprint(2, "usage: %s [-s steps]\n", argv0);
285 threadexitsall("usage");
289 threadmain(int argc, char **argv)
291 void simpleinit(void);
297 Steps = strtol(EARGF(usage()), &s, 0);
303 if(initdraw(nil, nil, nil) < 0) sysfatal("initdraw: %r");
304 mc = initmouse(nil, screen);
305 if(mc == nil) sysfatal("initmouse: %r");
306 kc = initkeyboard(nil);
307 if(kc == nil) sysfatal("initkeyboard: %r");
309 trayo.prev = trayo.next = &trayo;
310 worko.prev = worko.next = &worko;
311 runo.prev = runo.next = &runo;
314 flushimage(display, 1);
318 {mc->c, &mc->Mouse, CHANRCV},
319 {kc->c, &r, CHANRCV},
324 case 0: mouse(); break;
325 case 1: key(r); break;