tile_map.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  1. /*************************************************************************/
  2. /* tile_map.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* http://www.godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  9. /* */
  10. /* Permission is hereby granted, free of charge, to any person obtaining */
  11. /* a copy of this software and associated documentation files (the */
  12. /* "Software"), to deal in the Software without restriction, including */
  13. /* without limitation the rights to use, copy, modify, merge, publish, */
  14. /* distribute, sublicense, and/or sell copies of the Software, and to */
  15. /* permit persons to whom the Software is furnished to do so, subject to */
  16. /* the following conditions: */
  17. /* */
  18. /* The above copyright notice and this permission notice shall be */
  19. /* included in all copies or substantial portions of the Software. */
  20. /* */
  21. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  22. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  23. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  24. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  25. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  26. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  27. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  28. /*************************************************************************/
  29. #include "tile_map.h"
  30. #include "io/marshalls.h"
  31. #include "servers/physics_2d_server.h"
  32. #include "method_bind_ext.inc"
  33. void TileMap::_notification(int p_what) {
  34. switch(p_what) {
  35. case NOTIFICATION_ENTER_TREE: {
  36. pending_update=true;
  37. _update_dirty_quadrants();
  38. RID space = get_world_2d()->get_space();
  39. _update_quadrant_transform();
  40. _update_quadrant_space(space);
  41. } break;
  42. case NOTIFICATION_EXIT_TREE: {
  43. _update_quadrant_space(RID());
  44. } break;
  45. case NOTIFICATION_TRANSFORM_CHANGED: {
  46. //move stuff
  47. _update_quadrant_transform();
  48. } break;
  49. }
  50. }
  51. void TileMap::_update_quadrant_space(const RID& p_space) {
  52. for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
  53. Quadrant &q=E->get();
  54. Physics2DServer::get_singleton()->body_set_space(q.static_body,p_space);
  55. }
  56. }
  57. void TileMap::_update_quadrant_transform() {
  58. if (!is_inside_tree())
  59. return;
  60. Matrix32 global_transform = get_global_transform();
  61. for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
  62. Quadrant &q=E->get();
  63. Matrix32 xform;
  64. xform.set_origin( q.pos );
  65. xform = global_transform * xform;
  66. Physics2DServer::get_singleton()->body_set_state(q.static_body,Physics2DServer::BODY_STATE_TRANSFORM,xform);
  67. }
  68. }
  69. void TileMap::set_tileset(const Ref<TileSet>& p_tileset) {
  70. if (tile_set.is_valid())
  71. tile_set->disconnect("changed",this,"_recreate_quadrants");
  72. _clear_quadrants();
  73. tile_set=p_tileset;
  74. if (tile_set.is_valid())
  75. tile_set->connect("changed",this,"_recreate_quadrants");
  76. else
  77. clear();
  78. _recreate_quadrants();
  79. emit_signal("settings_changed");
  80. }
  81. Ref<TileSet> TileMap::get_tileset() const {
  82. return tile_set;
  83. }
  84. void TileMap::set_cell_size(Size2 p_size) {
  85. ERR_FAIL_COND(p_size.x<1 || p_size.y<1);
  86. _clear_quadrants();
  87. cell_size=p_size;
  88. _recreate_quadrants();
  89. emit_signal("settings_changed");
  90. }
  91. Size2 TileMap::get_cell_size() const {
  92. return cell_size;
  93. }
  94. void TileMap::set_quadrant_size(int p_size) {
  95. ERR_FAIL_COND(p_size<1);
  96. _clear_quadrants();
  97. quadrant_size=p_size;
  98. _recreate_quadrants();
  99. emit_signal("settings_changed");
  100. }
  101. int TileMap::get_quadrant_size() const {
  102. return quadrant_size;
  103. }
  104. void TileMap::set_center_x(bool p_enable) {
  105. center_x=p_enable;
  106. _recreate_quadrants();
  107. emit_signal("settings_changed");
  108. }
  109. bool TileMap::get_center_x() const {
  110. return center_x;
  111. }
  112. void TileMap::set_center_y(bool p_enable) {
  113. center_y=p_enable;
  114. _recreate_quadrants();
  115. emit_signal("settings_changed");
  116. }
  117. bool TileMap::get_center_y() const {
  118. return center_y;
  119. }
  120. void TileMap::_update_dirty_quadrants() {
  121. if (!pending_update)
  122. return;
  123. if (!is_inside_tree())
  124. return;
  125. if (!tile_set.is_valid())
  126. return;
  127. VisualServer *vs = VisualServer::get_singleton();
  128. Physics2DServer *ps = Physics2DServer::get_singleton();
  129. Vector2 tofs = get_cell_draw_offset();
  130. while (dirty_quadrant_list.first()) {
  131. Quadrant &q = *dirty_quadrant_list.first()->self();
  132. vs->canvas_item_clear(q.canvas_item);
  133. ps->body_clear_shapes(q.static_body);
  134. int shape_idx=0;
  135. for(int i=0;i<q.cells.size();i++) {
  136. Map<PosKey,Cell>::Element *E=tile_map.find( q.cells[i] );
  137. Cell &c=E->get();
  138. //moment of truth
  139. if (!tile_set->has_tile(c.id))
  140. continue;
  141. Ref<Texture> tex = tile_set->tile_get_texture(c.id);
  142. Vector2 tile_ofs = tile_set->tile_get_texture_offset(c.id);
  143. Vector2 offset = _map_to_world(E->key().x, E->key().y) - q.pos + tofs;
  144. if (!tex.is_valid())
  145. continue;
  146. Rect2 r = tile_set->tile_get_region(c.id);
  147. Size2 s = tex->get_size();
  148. if (r==Rect2())
  149. s = tex->get_size();
  150. else {
  151. s = r.size;
  152. r.pos.x+=fp_adjust;
  153. r.pos.y+=fp_adjust;
  154. r.size.x-=fp_adjust*2.0;
  155. r.size.y-=fp_adjust*2.0;
  156. }
  157. Rect2 rect;
  158. rect.pos=offset.floor();
  159. rect.size=s;
  160. rect.size.x+=fp_adjust;
  161. rect.size.y+=fp_adjust;
  162. if (c.flip_h)
  163. rect.size.x=-rect.size.x;
  164. if (c.flip_v)
  165. rect.size.y=-rect.size.y;
  166. rect.pos+=tile_ofs;
  167. if (r==Rect2()) {
  168. tex->draw_rect(q.canvas_item,rect,false,Color(1,1,1),c.transpose);
  169. } else {
  170. tex->draw_rect_region(q.canvas_item,rect,r,Color(1,1,1),c.transpose);
  171. }
  172. Vector< Ref<Shape2D> > shapes = tile_set->tile_get_shapes(c.id);
  173. for(int i=0;i<shapes.size();i++) {
  174. Ref<Shape2D> shape = shapes[i];
  175. if (shape.is_valid()) {
  176. Vector2 shape_ofs = tile_set->tile_get_shape_offset(c.id);
  177. Matrix32 xform;
  178. xform.set_origin(offset.floor());
  179. if (c.flip_h) {
  180. xform.elements[0]=-xform.elements[0];
  181. shape_ofs.x=s.x-shape_ofs.x;
  182. }
  183. if (c.flip_v) {
  184. xform.elements[1]=-xform.elements[1];
  185. shape_ofs.y=s.y-shape_ofs.y;
  186. }
  187. if (c.transpose) {
  188. SWAP(xform.elements[0].x, xform.elements[0].y);
  189. SWAP(xform.elements[1].x, xform.elements[1].y);
  190. SWAP(shape_ofs.x, shape_ofs.y);
  191. }
  192. xform.elements[2].x+=shape_ofs.x;
  193. xform.elements[2].y+=shape_ofs.y;
  194. ps->body_add_shape(q.static_body,shape->get_rid(),xform);
  195. ps->body_set_shape_metadata(q.static_body,shape_idx++,Vector2(E->key().x,E->key().y));
  196. }
  197. }
  198. }
  199. dirty_quadrant_list.remove( dirty_quadrant_list.first() );
  200. }
  201. pending_update=false;
  202. if (quadrant_order_dirty) {
  203. for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
  204. Quadrant &q=E->get();
  205. if (q.canvas_item.is_valid()) {
  206. VS::get_singleton()->canvas_item_raise(q.canvas_item);
  207. }
  208. }
  209. quadrant_order_dirty=false;
  210. }
  211. _recompute_rect_cache();
  212. }
  213. void TileMap::_recompute_rect_cache() {
  214. #ifdef DEBUG_ENABLED
  215. if (!rect_cache_dirty)
  216. return;
  217. Rect2 r_total;
  218. for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
  219. Rect2 r;
  220. r.pos=_map_to_world(E->key().x*quadrant_size, E->key().y*quadrant_size);
  221. r.expand_to( _map_to_world(E->key().x*quadrant_size+quadrant_size, E->key().y*quadrant_size) );
  222. r.expand_to( _map_to_world(E->key().x*quadrant_size+quadrant_size, E->key().y*quadrant_size+quadrant_size) );
  223. r.expand_to( _map_to_world(E->key().x*quadrant_size, E->key().y*quadrant_size+quadrant_size) );
  224. if (E==quadrant_map.front())
  225. r_total=r;
  226. else
  227. r_total=r_total.merge(r);
  228. }
  229. if (r_total==Rect2()) {
  230. rect_cache=Rect2(-10,-10,20,20);
  231. } else {
  232. rect_cache=r_total.grow(MAX(cell_size.x,cell_size.y)*quadrant_size);
  233. }
  234. item_rect_changed();
  235. rect_cache_dirty=false;
  236. #endif
  237. }
  238. Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const PosKey& p_qk) {
  239. Matrix32 xform;
  240. //xform.set_origin(Point2(p_qk.x,p_qk.y)*cell_size*quadrant_size);
  241. Quadrant q;
  242. q.pos = _map_to_world(p_qk.x*quadrant_size,p_qk.y*quadrant_size);
  243. xform.set_origin( q.pos );
  244. q.canvas_item = VisualServer::get_singleton()->canvas_item_create();
  245. VisualServer::get_singleton()->canvas_item_set_parent( q.canvas_item, get_canvas_item() );
  246. VisualServer::get_singleton()->canvas_item_set_transform( q.canvas_item, xform );
  247. q.static_body=Physics2DServer::get_singleton()->body_create(Physics2DServer::BODY_MODE_STATIC);
  248. Physics2DServer::get_singleton()->body_attach_object_instance_ID(q.static_body,get_instance_ID());
  249. Physics2DServer::get_singleton()->body_set_layer_mask(q.static_body,collision_layer);
  250. Physics2DServer::get_singleton()->body_set_param(q.static_body,Physics2DServer::BODY_PARAM_FRICTION,friction);
  251. Physics2DServer::get_singleton()->body_set_param(q.static_body,Physics2DServer::BODY_PARAM_BOUNCE,bounce);
  252. if (is_inside_tree()) {
  253. xform = get_global_transform() * xform;
  254. RID space = get_world_2d()->get_space();
  255. Physics2DServer::get_singleton()->body_set_space(q.static_body,space);
  256. }
  257. Physics2DServer::get_singleton()->body_set_state(q.static_body,Physics2DServer::BODY_STATE_TRANSFORM,xform);
  258. rect_cache_dirty=true;
  259. quadrant_order_dirty=true;
  260. return quadrant_map.insert(p_qk,q);
  261. }
  262. void TileMap::_erase_quadrant(Map<PosKey,Quadrant>::Element *Q) {
  263. Quadrant &q=Q->get();
  264. Physics2DServer::get_singleton()->free(q.static_body);
  265. VisualServer::get_singleton()->free(q.canvas_item);
  266. if (q.dirty_list.in_list())
  267. dirty_quadrant_list.remove(&q.dirty_list);
  268. quadrant_map.erase(Q);
  269. rect_cache_dirty=true;
  270. }
  271. void TileMap::_make_quadrant_dirty(Map<PosKey,Quadrant>::Element *Q) {
  272. Quadrant &q=Q->get();
  273. if (!q.dirty_list.in_list())
  274. dirty_quadrant_list.add(&q.dirty_list);
  275. if (pending_update)
  276. return;
  277. pending_update=true;
  278. if (!is_inside_tree())
  279. return;
  280. call_deferred("_update_dirty_quadrants");
  281. }
  282. void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y,bool p_transpose) {
  283. PosKey pk(p_x,p_y);
  284. Map<PosKey,Cell>::Element *E=tile_map.find(pk);
  285. if (!E && p_tile==INVALID_CELL)
  286. return; //nothing to do
  287. PosKey qk(p_x/quadrant_size,p_y/quadrant_size);
  288. if (p_tile==INVALID_CELL) {
  289. //erase existing
  290. tile_map.erase(pk);
  291. Map<PosKey,Quadrant>::Element *Q = quadrant_map.find(qk);
  292. ERR_FAIL_COND(!Q);
  293. Quadrant &q=Q->get();
  294. q.cells.erase(pk);
  295. if (q.cells.size()==0)
  296. _erase_quadrant(Q);
  297. else
  298. _make_quadrant_dirty(Q);
  299. return;
  300. }
  301. Map<PosKey,Quadrant>::Element *Q = quadrant_map.find(qk);
  302. if (!E) {
  303. E=tile_map.insert(pk,Cell());
  304. if (!Q) {
  305. Q=_create_quadrant(qk);
  306. }
  307. Quadrant &q=Q->get();
  308. q.cells.insert(pk);
  309. } else {
  310. ERR_FAIL_COND(!Q); // quadrant should exist...
  311. if (E->get().id==p_tile && E->get().flip_h==p_flip_x && E->get().flip_v==p_flip_y && E->get().transpose==p_transpose)
  312. return; //nothing changed
  313. }
  314. Cell &c = E->get();
  315. c.id=p_tile;
  316. c.flip_h=p_flip_x;
  317. c.flip_v=p_flip_y;
  318. c.transpose=p_transpose;
  319. _make_quadrant_dirty(Q);
  320. }
  321. int TileMap::get_cell(int p_x,int p_y) const {
  322. PosKey pk(p_x,p_y);
  323. const Map<PosKey,Cell>::Element *E=tile_map.find(pk);
  324. if (!E)
  325. return INVALID_CELL;
  326. return E->get().id;
  327. }
  328. bool TileMap::is_cell_x_flipped(int p_x,int p_y) const {
  329. PosKey pk(p_x,p_y);
  330. const Map<PosKey,Cell>::Element *E=tile_map.find(pk);
  331. if (!E)
  332. return false;
  333. return E->get().flip_h;
  334. }
  335. bool TileMap::is_cell_y_flipped(int p_x,int p_y) const {
  336. PosKey pk(p_x,p_y);
  337. const Map<PosKey,Cell>::Element *E=tile_map.find(pk);
  338. if (!E)
  339. return false;
  340. return E->get().flip_v;
  341. }
  342. bool TileMap::is_cell_transposed(int p_x,int p_y) const {
  343. PosKey pk(p_x,p_y);
  344. const Map<PosKey,Cell>::Element *E=tile_map.find(pk);
  345. if (!E)
  346. return false;
  347. return E->get().transpose;
  348. }
  349. void TileMap::_recreate_quadrants() {
  350. _clear_quadrants();
  351. for (Map<PosKey,Cell>::Element *E=tile_map.front();E;E=E->next()) {
  352. PosKey qk(E->key().x/quadrant_size,E->key().y/quadrant_size);
  353. Map<PosKey,Quadrant>::Element *Q=quadrant_map.find(qk);
  354. if (!Q) {
  355. Q=_create_quadrant(qk);
  356. dirty_quadrant_list.add(&Q->get().dirty_list);
  357. }
  358. Q->get().cells.insert(E->key());
  359. _make_quadrant_dirty(Q);
  360. }
  361. }
  362. void TileMap::_clear_quadrants() {
  363. while (quadrant_map.size()) {
  364. _erase_quadrant( quadrant_map.front() );
  365. }
  366. }
  367. void TileMap::clear() {
  368. _clear_quadrants();
  369. tile_map.clear();
  370. }
  371. void TileMap::_set_tile_data(const DVector<int>& p_data) {
  372. int c=p_data.size();
  373. DVector<int>::Read r = p_data.read();
  374. for(int i=0;i<c;i+=2) {
  375. const uint8_t *ptr=(const uint8_t*)&r[i];
  376. uint8_t local[8];
  377. for(int j=0;j<8;j++)
  378. local[j]=ptr[j];
  379. #ifdef BIG_ENDIAN_ENABLED
  380. SWAP(local[0],local[3]);
  381. SWAP(local[1],local[2]);
  382. SWAP(local[4],local[7]);
  383. SWAP(local[5],local[6]);
  384. #endif
  385. int16_t x = decode_uint16(&local[0]);
  386. int16_t y = decode_uint16(&local[2]);
  387. uint32_t v = decode_uint32(&local[4]);
  388. bool flip_h = v&(1<<29);
  389. bool flip_v = v&(1<<30);
  390. bool transpose = v&(1<<31);
  391. v&=(1<<29)-1;
  392. // if (x<-20 || y <-20 || x>4000 || y>4000)
  393. // continue;
  394. set_cell(x,y,v,flip_h,flip_v,transpose);
  395. }
  396. }
  397. DVector<int> TileMap::_get_tile_data() const {
  398. DVector<int> data;
  399. data.resize(tile_map.size()*2);
  400. DVector<int>::Write w = data.write();
  401. int idx=0;
  402. for(const Map<PosKey,Cell>::Element *E=tile_map.front();E;E=E->next()) {
  403. uint8_t *ptr = (uint8_t*)&w[idx];
  404. encode_uint16(E->key().x,&ptr[0]);
  405. encode_uint16(E->key().y,&ptr[2]);
  406. uint32_t val = E->get().id;
  407. if (E->get().flip_h)
  408. val|=(1<<29);
  409. if (E->get().flip_v)
  410. val|=(1<<30);
  411. if (E->get().transpose)
  412. val|=(1<<31);
  413. encode_uint32(val,&ptr[4]);
  414. idx+=2;
  415. }
  416. w = DVector<int>::Write();
  417. return data;
  418. }
  419. Rect2 TileMap::get_item_rect() const {
  420. const_cast<TileMap*>(this)->_update_dirty_quadrants();
  421. return rect_cache;
  422. }
  423. void TileMap::set_collision_layer_mask(uint32_t p_layer) {
  424. collision_layer=p_layer;
  425. for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
  426. Quadrant &q=E->get();
  427. Physics2DServer::get_singleton()->body_set_layer_mask(q.static_body,collision_layer);
  428. }
  429. }
  430. void TileMap::set_collision_friction(float p_friction) {
  431. friction=p_friction;
  432. for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
  433. Quadrant &q=E->get();
  434. Physics2DServer::get_singleton()->body_set_param(q.static_body,Physics2DServer::BODY_PARAM_FRICTION,p_friction);
  435. }
  436. }
  437. float TileMap::get_collision_friction() const{
  438. return friction;
  439. }
  440. void TileMap::set_collision_bounce(float p_bounce){
  441. bounce=p_bounce;
  442. for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
  443. Quadrant &q=E->get();
  444. Physics2DServer::get_singleton()->body_set_param(q.static_body,Physics2DServer::BODY_PARAM_BOUNCE,p_bounce);
  445. }
  446. }
  447. float TileMap::get_collision_bounce() const{
  448. return bounce;
  449. }
  450. uint32_t TileMap::get_collision_layer_mask() const {
  451. return collision_layer;
  452. }
  453. void TileMap::set_mode(Mode p_mode) {
  454. _clear_quadrants();
  455. mode=p_mode;
  456. _recreate_quadrants();
  457. emit_signal("settings_changed");
  458. }
  459. TileMap::Mode TileMap::get_mode() const {
  460. return mode;
  461. }
  462. void TileMap::set_half_offset(HalfOffset p_half_offset) {
  463. _clear_quadrants();
  464. half_offset=p_half_offset;
  465. _recreate_quadrants();
  466. emit_signal("settings_changed");
  467. }
  468. Vector2 TileMap::get_cell_draw_offset() const {
  469. switch(mode) {
  470. case MODE_SQUARE: {
  471. return Vector2();
  472. } break;
  473. case MODE_ISOMETRIC: {
  474. return Vector2(-cell_size.x*0.5,0);
  475. } break;
  476. case MODE_CUSTOM: {
  477. Vector2 min;
  478. min.x = MIN(custom_transform[0].x,min.x);
  479. min.y = MIN(custom_transform[0].y,min.y);
  480. min.x = MIN(custom_transform[1].x,min.x);
  481. min.y = MIN(custom_transform[1].y,min.y);
  482. return min;
  483. } break;
  484. }
  485. return Vector2();
  486. }
  487. TileMap::HalfOffset TileMap::get_half_offset() const {
  488. return half_offset;
  489. }
  490. Matrix32 TileMap::get_cell_transform() const {
  491. switch(mode) {
  492. case MODE_SQUARE: {
  493. Matrix32 m;
  494. m[0]*=cell_size.x;
  495. m[1]*=cell_size.y;
  496. return m;
  497. } break;
  498. case MODE_ISOMETRIC: {
  499. //isometric only makes sense when y is positive in both x and y vectors, otherwise
  500. //the drawing of tiles will overlap
  501. Matrix32 m;
  502. m[0]=Vector2(cell_size.x*0.5,cell_size.y*0.5);
  503. m[1]=Vector2(-cell_size.x*0.5,cell_size.y*0.5);
  504. return m;
  505. } break;
  506. case MODE_CUSTOM: {
  507. return custom_transform;
  508. } break;
  509. }
  510. return Matrix32();
  511. }
  512. void TileMap::set_custom_transform(const Matrix32& p_xform) {
  513. _clear_quadrants();
  514. custom_transform=p_xform;
  515. _recreate_quadrants();
  516. emit_signal("settings_changed");
  517. }
  518. Matrix32 TileMap::get_custom_transform() const{
  519. return custom_transform;
  520. }
  521. Vector2 TileMap::_map_to_world(int x,int y,bool p_ignore_ofs) const {
  522. Vector2 ret = get_cell_transform().xform(Vector2(x,y));
  523. if (!p_ignore_ofs) {
  524. switch(half_offset) {
  525. case HALF_OFFSET_X: {
  526. if (ABS(y)&1) {
  527. ret+=get_cell_transform()[0]*0.5;
  528. }
  529. } break;
  530. case HALF_OFFSET_Y: {
  531. if (ABS(x)&1) {
  532. ret+=get_cell_transform()[1]*0.5;
  533. }
  534. } break;
  535. default: {}
  536. }
  537. }
  538. return ret;
  539. }
  540. Vector2 TileMap::map_to_world(const Vector2& p_pos,bool p_ignore_ofs) const {
  541. return _map_to_world(p_pos.x,p_pos.y,p_ignore_ofs);
  542. }
  543. Vector2 TileMap::world_to_map(const Vector2& p_pos) const{
  544. Vector2 ret = get_cell_transform().affine_inverse().xform(p_pos);
  545. switch(half_offset) {
  546. case HALF_OFFSET_X: {
  547. if (int(ret.y)&1) {
  548. ret.x-=0.5;
  549. }
  550. } break;
  551. case HALF_OFFSET_Y: {
  552. if (int(ret.x)&1) {
  553. ret.y-=0.5;
  554. }
  555. } break;
  556. default: {}
  557. }
  558. return ret.floor();
  559. }
  560. void TileMap::_bind_methods() {
  561. ObjectTypeDB::bind_method(_MD("set_tileset","tileset:TileSet"),&TileMap::set_tileset);
  562. ObjectTypeDB::bind_method(_MD("get_tileset:TileSet"),&TileMap::get_tileset);
  563. ObjectTypeDB::bind_method(_MD("set_mode","mode"),&TileMap::set_mode);
  564. ObjectTypeDB::bind_method(_MD("get_mode"),&TileMap::get_mode);
  565. ObjectTypeDB::bind_method(_MD("set_half_offset","half_offset"),&TileMap::set_half_offset);
  566. ObjectTypeDB::bind_method(_MD("get_half_offset"),&TileMap::get_half_offset);
  567. ObjectTypeDB::bind_method(_MD("set_custom_transform","custom_transform"),&TileMap::set_custom_transform);
  568. ObjectTypeDB::bind_method(_MD("get_custom_transform"),&TileMap::get_custom_transform);
  569. ObjectTypeDB::bind_method(_MD("set_cell_size","size"),&TileMap::set_cell_size);
  570. ObjectTypeDB::bind_method(_MD("get_cell_size"),&TileMap::get_cell_size);
  571. ObjectTypeDB::bind_method(_MD("_set_old_cell_size","size"),&TileMap::_set_old_cell_size);
  572. ObjectTypeDB::bind_method(_MD("_get_old_cell_size"),&TileMap::_get_old_cell_size);
  573. ObjectTypeDB::bind_method(_MD("set_quadrant_size","size"),&TileMap::set_quadrant_size);
  574. ObjectTypeDB::bind_method(_MD("get_quadrant_size"),&TileMap::get_quadrant_size);
  575. ObjectTypeDB::bind_method(_MD("set_center_x","enable"),&TileMap::set_center_x);
  576. ObjectTypeDB::bind_method(_MD("get_center_x"),&TileMap::get_center_x);
  577. ObjectTypeDB::bind_method(_MD("set_center_y","enable"),&TileMap::set_center_y);
  578. ObjectTypeDB::bind_method(_MD("get_center_y"),&TileMap::get_center_y);
  579. ObjectTypeDB::bind_method(_MD("set_collision_layer_mask","mask"),&TileMap::set_collision_layer_mask);
  580. ObjectTypeDB::bind_method(_MD("get_collision_layer_mask"),&TileMap::get_collision_layer_mask);
  581. ObjectTypeDB::bind_method(_MD("set_collision_friction","value"),&TileMap::set_collision_friction);
  582. ObjectTypeDB::bind_method(_MD("get_collision_friction"),&TileMap::get_collision_friction);
  583. ObjectTypeDB::bind_method(_MD("set_collision_bounce","value"),&TileMap::set_collision_bounce);
  584. ObjectTypeDB::bind_method(_MD("get_collision_bounce"),&TileMap::get_collision_bounce);
  585. ObjectTypeDB::bind_method(_MD("set_cell","x","y","tile","flip_x","flip_y","transpose"),&TileMap::set_cell,DEFVAL(false),DEFVAL(false),DEFVAL(false));
  586. ObjectTypeDB::bind_method(_MD("get_cell","x","y"),&TileMap::get_cell);
  587. ObjectTypeDB::bind_method(_MD("is_cell_x_flipped","x","y"),&TileMap::is_cell_x_flipped);
  588. ObjectTypeDB::bind_method(_MD("is_cell_y_flipped","x","y"),&TileMap::is_cell_y_flipped);
  589. ObjectTypeDB::bind_method(_MD("clear"),&TileMap::clear);
  590. ObjectTypeDB::bind_method(_MD("map_to_world","mappos","ignore_half_ofs"),&TileMap::map_to_world,DEFVAL(false));
  591. ObjectTypeDB::bind_method(_MD("world_to_map","worldpos"),&TileMap::world_to_map);
  592. ObjectTypeDB::bind_method(_MD("_clear_quadrants"),&TileMap::_clear_quadrants);
  593. ObjectTypeDB::bind_method(_MD("_recreate_quadrants"),&TileMap::_recreate_quadrants);
  594. ObjectTypeDB::bind_method(_MD("_update_dirty_quadrants"),&TileMap::_update_dirty_quadrants);
  595. ObjectTypeDB::bind_method(_MD("_set_tile_data"),&TileMap::_set_tile_data);
  596. ObjectTypeDB::bind_method(_MD("_get_tile_data"),&TileMap::_get_tile_data);
  597. ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Square,Isometric,Custom"),_SCS("set_mode"),_SCS("get_mode"));
  598. ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_set",PROPERTY_HINT_RESOURCE_TYPE,"TileSet"),_SCS("set_tileset"),_SCS("get_tileset"));
  599. ADD_PROPERTY( PropertyInfo(Variant::INT,"cell_size",PROPERTY_HINT_RANGE,"1,8192,1",0),_SCS("_set_old_cell_size"),_SCS("_get_old_cell_size"));
  600. ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"cell/size",PROPERTY_HINT_RANGE,"1,8192,1"),_SCS("set_cell_size"),_SCS("get_cell_size"));
  601. ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/quadrant_size",PROPERTY_HINT_RANGE,"1,128,1"),_SCS("set_quadrant_size"),_SCS("get_quadrant_size"));
  602. ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"cell/custom_transform"),_SCS("set_custom_transform"),_SCS("get_custom_transform"));
  603. ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/half_offset",PROPERTY_HINT_ENUM,"Offset X,Offset Y,Disabled"),_SCS("set_half_offset"),_SCS("get_half_offset"));
  604. ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_friction"),_SCS("get_collision_friction"));
  605. ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_bounce"),_SCS("get_collision_bounce"));
  606. ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_layer_mask"),_SCS("get_collision_layer_mask"));
  607. ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_tile_data"),_SCS("_get_tile_data"));
  608. ADD_SIGNAL(MethodInfo("settings_changed"));
  609. BIND_CONSTANT( INVALID_CELL );
  610. BIND_CONSTANT( MODE_SQUARE );
  611. BIND_CONSTANT( MODE_ISOMETRIC );
  612. BIND_CONSTANT( MODE_CUSTOM );
  613. BIND_CONSTANT( HALF_OFFSET_X );
  614. BIND_CONSTANT( HALF_OFFSET_Y );
  615. BIND_CONSTANT( HALF_OFFSET_DISABLED );
  616. }
  617. TileMap::TileMap() {
  618. rect_cache_dirty=true;
  619. pending_update=false;
  620. quadrant_order_dirty=false;
  621. quadrant_size=16;
  622. cell_size=Size2(64,64);
  623. center_x=false;
  624. center_y=false;
  625. collision_layer=1;
  626. friction=1;
  627. bounce=0;
  628. mode=MODE_SQUARE;
  629. half_offset=HALF_OFFSET_DISABLED;
  630. fp_adjust=0.01;
  631. fp_adjust=0.01;
  632. }
  633. TileMap::~TileMap() {
  634. clear();
  635. }