st_edit.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. /********************************************************************** <BR>
  2. This file is part of Crack dot Com's free source code release of
  3. Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
  4. information about compiling & licensing issues visit this URL</a>
  5. <PRE> If that doesn't help, contact Jonathan Clark at
  6. golgotha_source@usa.net (Subject should have "GOLG" in it)
  7. ***********************************************************************/
  8. #include "st_edit.hh"
  9. #include "m1_info.hh"
  10. #include "window/window.hh"
  11. #include "gtext_load.hh"
  12. #include "image/image.hh"
  13. #include "max_object.hh"
  14. #include "window/win_evt.hh"
  15. #include "device/kernel.hh"
  16. #include "render.hh"
  17. #include "app/app.hh"
  18. #include "window/wmanager.hh"
  19. #include "gui/text_input.hh"
  20. #include "tmanage.hh"
  21. #define HANDLE_SIZE 3
  22. #define SNAP_DISTANCE 5
  23. i4_float m1_st_edit_window_class::twidth() const
  24. {
  25. return (texture)? texture->width()-0.0001 : 255.9999;
  26. }
  27. i4_float m1_st_edit_window_class::theight() const
  28. {
  29. return (texture)? texture->height()-0.0001 : 255.9999;
  30. }
  31. void m1_st_edit_window_class::get_point(int poly, int num, int &x, int &y)
  32. {
  33. if (m1_info.obj)
  34. {
  35. g1_quad_class *q=m1_info.obj->quad+poly;
  36. float tw=twidth(), th=theight();
  37. x=(int)(q->u[num] * tw);
  38. y=(int)(q->v[num] * th);
  39. }
  40. }
  41. void m1_st_edit_window_class::draw(i4_draw_context_class &context)
  42. {
  43. local_image->clear(0, context);
  44. if (texture)
  45. texture->put_image(local_image, 0,0, context);
  46. if (m1_info.obj)
  47. {
  48. w32 c=0x0000ff; //(254<<16)|(2<<8)|166;
  49. int x1,y1,x2,y2;
  50. for (int j=0; j<m1_info.obj->num_quad; j++)
  51. {
  52. if (m1_info.obj->quad[j].get_flags(g1_quad_class::SELECTED))
  53. {
  54. int i;
  55. g1_quad_class *q=&m1_info.obj->quad[j];
  56. get_point(j,0,x2,y2);
  57. for (i=q->num_verts()-1; i>=0; i--)
  58. {
  59. get_point(j,i,x1,y1);
  60. local_image->line(x1,y1,x2,y2, c, context);
  61. x2 = x1; y2 = y1;
  62. }
  63. for (i=0; i<q->num_verts(); i++)
  64. {
  65. int x,y;
  66. get_point(j,i,x,y);
  67. if (m1_info.obj->get_poly_vert_flag(j,1<<i))
  68. local_image->bar(x-2,y-2,x+2,y+2, 0xffff00, context);
  69. else
  70. local_image->bar(x-2,y-2,x+2,y+2, 0x808080, context);
  71. }
  72. }
  73. }
  74. if (preselect_x>=0)
  75. local_image->bar(preselect_x-2,preselect_y-2,preselect_x+2,preselect_y+2, 0xff00ff, context);
  76. }
  77. }
  78. void m1_st_edit_window_class::drag_points(int xc, int yc)
  79. {
  80. m1_poly_object_class *obj=m1_info.obj;
  81. if (!obj) return;
  82. float tw=twidth(), th=theight();
  83. float u_change=xc/tw, v_change=yc/th;
  84. i4_bool change=i4_F;
  85. for (int i=0; i<m1_info.obj->num_quad; i++)
  86. {
  87. if (obj->quad[i].get_flags(g1_quad_class::SELECTED))
  88. {
  89. for (int j=0; j<obj->quad[i].num_verts(); j++)
  90. {
  91. if (obj->get_poly_vert_flag(i, 1<<j))
  92. {
  93. obj->quad[i].u[j]+=u_change;
  94. if (obj->quad[i].u[j]<0) obj->quad[i].u[j]=0;
  95. if (obj->quad[i].u[j]>1) obj->quad[i].u[j]=1;
  96. obj->quad[i].v[j]+=v_change;
  97. if (obj->quad[i].v[j]<0) obj->quad[i].v[j]=0;
  98. if (obj->quad[i].v[j]>1) obj->quad[i].v[j]=1;
  99. change=i4_T;
  100. }
  101. }
  102. }
  103. }
  104. if (change)
  105. {
  106. obj->calc_texture_scales();
  107. request_redraw(i4_F);
  108. if (m1_render_window.get())
  109. m1_render_window->request_redraw(i4_F);
  110. }
  111. }
  112. i4_bool m1_st_edit_window_class::verts_are_selected()
  113. {
  114. if (!m1_info.obj)
  115. return 0;
  116. for (int j=0; j<m1_info.obj->num_quad; j++)
  117. if (m1_info.obj->quad[j].get_flags(g1_quad_class::SELECTED))
  118. {
  119. for (int i=0; i<m1_info.obj->quad[j].num_verts(); i++)
  120. if (m1_info.obj->get_poly_vert_flag(j,1<<i))
  121. return i4_T;
  122. }
  123. return i4_F;
  124. }
  125. void m1_st_edit_window_class::select_point(int point)
  126. {
  127. if (!m1_info.obj)
  128. return;
  129. if (point<0)
  130. return;
  131. m1_poly_object_class *obj=m1_info.obj;
  132. if (!i4_current_app->get_window_manager()->shift_pressed())
  133. {
  134. for (int j=0; j<obj->num_quad; j++)
  135. for (int i=0; i<4; i++)
  136. obj->set_poly_vert_flag(j, 1<<i, 0);
  137. }
  138. for (int j=0; j<obj->num_quad; j++)
  139. {
  140. g1_quad_class *q=obj->quad+j;
  141. if (q->get_flags(g1_quad_class::SELECTED))
  142. for (int i=0; i<q->num_verts(); i++)
  143. if (q->vertex_ref[i] == point)
  144. obj->set_poly_vert_flag(j, 1<<i, 1);
  145. }
  146. request_redraw();
  147. }
  148. void m1_st_edit_window_class::change_current_verts()
  149. {
  150. if (!m1_info.obj)
  151. return;
  152. int old_px = preselect_x;
  153. int old_py = preselect_y;
  154. preselect_x = -1;
  155. if (m1_info.preselect_point>=0)
  156. for (int j=0; j<m1_info.obj->num_quad; j++)
  157. if (m1_info.obj->quad[j].get_flags(g1_quad_class::SELECTED))
  158. {
  159. for (int i=0; i<m1_info.obj->quad[j].num_verts(); i++)
  160. if (m1_info.obj->quad[j].vertex_ref[i] == m1_info.preselect_point)
  161. get_point(j,i,preselect_x,preselect_y);
  162. }
  163. if (preselect_x!=old_px || preselect_y!=old_py)
  164. request_redraw();
  165. }
  166. void m1_st_edit_window_class::change_current_texture(i4_const_str new_name)
  167. {
  168. if (m1_info.obj)
  169. {
  170. i4_file_class *fp=i4_open(new_name);
  171. if (!fp) return;
  172. delete fp;
  173. int i;
  174. for (i=0; i<m1_info.obj->num_quad; i++)
  175. if (m1_info.obj->quad[i].get_flags(g1_quad_class::SELECTED))
  176. {
  177. delete m1_info.obj->texture_names[i];
  178. m1_info.obj->texture_names[i]=new i4_str(new_name);
  179. }
  180. m1_info.texture_list_changed();
  181. }
  182. }
  183. void m1_st_edit_window_class::receive_event(i4_event *ev)
  184. {
  185. int pre_grab = grab;
  186. m1_poly_object_class *obj=m1_info.obj;
  187. if (!obj)
  188. return ;
  189. switch (ev->type())
  190. {
  191. case i4_event::WINDOW_MESSAGE:
  192. {
  193. CAST_PTR(wev, i4_window_message_class, ev);
  194. if (wev->sub_type==i4_window_message_class::GOT_DROP)
  195. i4_kernel.send_event(tname_edit, ev);
  196. } break;
  197. case i4_event::OBJECT_MESSAGE :
  198. {
  199. CAST_PTR(tc, i4_text_change_notify_event, ev);
  200. if (tc->object==tname_edit && tc->new_text && m1_info.obj)
  201. {
  202. i4_file_class *fp=i4_open(*tc->new_text);
  203. if (!fp) return;
  204. delete fp;
  205. int i;
  206. for (i=0; i<m1_info.obj->num_quad; i++)
  207. if (m1_info.obj->quad[i].get_flags(g1_quad_class::SELECTED))
  208. m1_info.obj->texture_names[i]=new i4_str(*tc->new_text);
  209. m1_info.texture_list_changed();
  210. }
  211. } break;
  212. case i4_event::MOUSE_BUTTON_DOWN :
  213. {
  214. CAST_PTR(bev, i4_mouse_button_down_event_class, ev);
  215. if (bev->left()) grab |= LEFT;
  216. if (bev->right()) grab |= RIGHT;
  217. if (bev->center()) grab |= MIDDLE;
  218. i4_window_request_key_grab_class kgrab(this);
  219. i4_kernel.send_event(parent, &kgrab);
  220. i4_bool clear_old=i4_T;
  221. int sel_poly=-1, sel_vert=-1;
  222. if (bev->left() && obj)
  223. {
  224. for (int j=0; j<obj->num_quad; j++)
  225. {
  226. g1_quad_class *q=obj->quad+j;
  227. if (q->get_flags(g1_quad_class::SELECTED))
  228. {
  229. for (int i=0; i<q->num_verts(); i++)
  230. {
  231. int x,y;
  232. get_point(j,i,x,y);
  233. if (abs(bev->x-x)<HANDLE_SIZE && abs(bev->y-y)<HANDLE_SIZE)
  234. {
  235. if (obj->get_poly_vert_flag(j, 1<<i))
  236. clear_old=i4_F;
  237. else
  238. obj->set_poly_vert_flag(j, 1<<i, 1);
  239. sel_poly=j;
  240. sel_vert=i;
  241. }
  242. }
  243. }
  244. }
  245. }
  246. if (clear_old && !i4_current_app->get_window_manager()->shift_pressed())
  247. {
  248. for (int j=0; j<obj->num_quad; j++)
  249. for (int i=0; i<4; i++)
  250. obj->set_poly_vert_flag(j, 1<<i, 0);
  251. if (sel_poly!=-1)
  252. obj->set_poly_vert_flag(sel_poly, 1<<sel_vert, 1);
  253. }
  254. request_redraw(i4_T);
  255. } break;
  256. case i4_event::MOUSE_BUTTON_UP :
  257. {
  258. CAST_PTR(bev, i4_mouse_button_up_event_class, ev);
  259. if (bev->left()) grab &= ~LEFT;
  260. if (bev->right()) grab &= ~RIGHT;
  261. if (bev->center()) grab &= ~MIDDLE;
  262. } break;
  263. case i4_event::MOUSE_MOVE :
  264. {
  265. CAST_PTR(mev, i4_mouse_move_event_class, ev);
  266. int old_px = preselect_x, old_py = preselect_y;
  267. preselect_x = -1;
  268. if (m1_info.obj)
  269. {
  270. if (grab && verts_are_selected())
  271. {
  272. int snap_x = mev->x, snap_y = mev->y;
  273. for (int j=0; j<m1_info.obj->num_quad; j++)
  274. {
  275. g1_quad_class *q=m1_info.obj->quad+j;
  276. if (q->get_flags(g1_quad_class::SELECTED))
  277. {
  278. for (int i=0; i<q->num_verts(); i++)
  279. {
  280. if (!m1_info.obj->get_poly_vert_flag(j,1<<i))
  281. {
  282. int x,y;
  283. get_point(j,i,x,y);
  284. if (abs(mev->x-x)<SNAP_DISTANCE && abs(mev->y-y)<SNAP_DISTANCE)
  285. {
  286. snap_x = x;
  287. snap_y = y;
  288. }
  289. }
  290. }
  291. }
  292. }
  293. drag_points(snap_x+snap_off_x-mev->lx, snap_y+snap_off_y-mev->ly);
  294. snap_off_x = mev->x - snap_x;
  295. snap_off_y = mev->y - snap_y;
  296. }
  297. else
  298. {
  299. for (int j=0; j<m1_info.obj->num_quad; j++)
  300. {
  301. g1_quad_class *q=m1_info.obj->quad+j;
  302. if (q->get_flags(g1_quad_class::SELECTED))
  303. {
  304. for (int i=0; i<q->num_verts(); i++)
  305. {
  306. int x,y;
  307. get_point(j,i,x,y);
  308. if (abs(mev->x-x)<HANDLE_SIZE && abs(mev->y-y)<HANDLE_SIZE)
  309. {
  310. preselect_x = x;
  311. preselect_y = y;
  312. snap_off_x = mev->x - preselect_x;
  313. snap_off_y = mev->y - preselect_y;
  314. }
  315. }
  316. }
  317. }
  318. }
  319. if (old_px!=preselect_x || old_py!=preselect_y)
  320. request_redraw();
  321. }
  322. } break;
  323. }
  324. if (!pre_grab && grab)
  325. {
  326. i4_window_request_mouse_grab_class grab_ev(this);
  327. i4_kernel.send_event(parent,&grab_ev);
  328. }
  329. if (pre_grab && !grab)
  330. {
  331. i4_window_request_mouse_ungrab_class grab_ev(this);
  332. i4_kernel.send_event(parent,&grab_ev);
  333. }
  334. }
  335. void m1_st_edit_window_class::edit_poly_changed()
  336. {
  337. if (texture)
  338. delete texture;
  339. texture=0;
  340. if (m1_info.obj)
  341. {
  342. m1_poly_object_class *obj=m1_info.obj;
  343. int sel_poly=-1;
  344. for (int j=0; j<obj->num_quad; j++)
  345. if (obj->quad[j].get_flags(g1_quad_class::SELECTED))
  346. {
  347. if (sel_poly==-1)
  348. sel_poly=j;
  349. else if (sel_poly>=0)
  350. if (!(*obj->texture_names[sel_poly] == *obj->texture_names[j]))
  351. sel_poly=-2;
  352. }
  353. if (sel_poly==-1)
  354. tname_edit->change_text("<None Selected>");
  355. else if (sel_poly==-2)
  356. tname_edit->change_text("<Multiple Selected>");
  357. else
  358. {
  359. i4_image_class *im[10];
  360. int t=r1_load_gtext(r1_get_texture_id(*obj->texture_names[sel_poly]), im);
  361. for (int i=1; i<t; i++)
  362. delete im[i];
  363. if (t)
  364. texture=im[0];
  365. if (texture)
  366. tname_edit->change_text(*obj->texture_names[sel_poly]);
  367. else
  368. tname_edit->change_text("<Untextured>");
  369. }
  370. }
  371. request_redraw(i4_F);
  372. }
  373. m1_st_edit_window_class::m1_st_edit_window_class(w16 w, w16 h,
  374. i4_text_input_class *tname_edit)
  375. : i4_window_class(w,h),
  376. tname_edit(tname_edit)
  377. {
  378. texture=0;
  379. dragging=i4_F;
  380. preselect_x = -1;
  381. grab=0;
  382. }
  383. i4_event_handler_reference_class<m1_st_edit_window_class> m1_st_edit;