OverlayBrush.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. #define OVERLAYBRUSH_CPP
  2. /*************************************************************************************************\
  3. OverlayBrush.cpp : Implementation of the OverlayBrush component.
  4. //---------------------------------------------------------------------------//
  5. // Copyright (C) Microsoft Corporation. All rights reserved. //
  6. //===========================================================================//
  7. \*************************************************************************************************/
  8. #include "OverlayBrush.h"
  9. #include "Action.h"
  10. #include "EList.h"
  11. #include <map>
  12. //-------------------------------------------------------------------------------------------------
  13. class OTMap : public std::map<int, Overlays> {};
  14. static OTMap *pOverlaysToTransitionMapping = 0;
  15. class TOMap : public std::map<Overlays, int> {};
  16. static TOMap *pTransitionToOverlaysMapping = 0;
  17. static int UP = 0;
  18. static int RIGHT = 1;
  19. static int DOWN = 2;
  20. static int LEFT = 3;
  21. static Overlays IntToOverlayType(int i) {
  22. if (0xff <= i) {
  23. return INVALID_OVERLAY;
  24. } else {
  25. return (Overlays)i;
  26. }
  27. }
  28. static int OverlayTypeToInt(Overlays oOverlayType) {
  29. if (INVALID_OVERLAY == oOverlayType) {
  30. return 0xff;
  31. } else {
  32. return (int)oOverlayType;
  33. }
  34. }
  35. static Overlays overlayType(int mask, int direction) {
  36. if ((0 <= direction) && (4 > direction)) {
  37. return IntToOverlayType((mask >> (8*direction)) & 0xff);
  38. }
  39. gosASSERT(false);
  40. return INVALID_OVERLAY;
  41. }
  42. static void setOverlayType(int &mask, int direction, Overlays overlayType) {
  43. if ((0 <= direction) && (4 > direction)) {
  44. mask &= ~(0xff << (8*direction));
  45. mask |= ((OverlayTypeToInt(overlayType) & 0xff) << (8*direction));
  46. } else {
  47. gosASSERT(false);
  48. }
  49. }
  50. #define CONNECTIVITY_MASK(up, right, down, left) ((OverlayTypeToInt(up) & 0xff) + ((OverlayTypeToInt(right) & 0xff) << 8) + ((OverlayTypeToInt(down) & 0xff) << 16) + ((OverlayTypeToInt(left) & 0xff) << 24))
  51. static int connectivityMask(Overlays up, Overlays right, Overlays down, Overlays left) {
  52. return CONNECTIVITY_MASK(up, right, down, left);
  53. }
  54. static int connectivityMask() {
  55. return connectivityMask(INVALID_OVERLAY, INVALID_OVERLAY, INVALID_OVERLAY, INVALID_OVERLAY);
  56. }
  57. static int numberOfOverlayTypes(int mask) {
  58. EList<Overlays, Overlays> overlayTypeList;
  59. int i;
  60. for (i = 0; i < 4; i++) {
  61. Overlays type = overlayType(mask, i);
  62. if (INVALID_OVERLAY != type) {
  63. if ((0 == overlayTypeList.Count()) || (EList<Overlays, Overlays>::INVALID_ITERATOR == overlayTypeList.Find(type))) {
  64. overlayTypeList.Append(type);
  65. }
  66. }
  67. }
  68. return overlayTypeList.Count();
  69. }
  70. /* Non-transition overlays */
  71. static int ConnectivityMaskToIndexOffsetMapping[16] =
  72. {6, 13, 12, 5, 11, 0, 4, 10, 14, 2, 1, 7, 3, 8, 9, 6 };
  73. #define IOM_UP 1
  74. #define IOM_RIGHT 2
  75. #define IOM_DOWN 4
  76. #define IOM_LEFT 8
  77. static int IndexOffsetToConnectivityMaskMapping[15] =
  78. {
  79. IOM_UP | IOM_DOWN,
  80. IOM_RIGHT | IOM_LEFT,
  81. IOM_UP | IOM_LEFT,
  82. IOM_DOWN | IOM_LEFT,
  83. IOM_RIGHT | IOM_DOWN,
  84. IOM_UP | IOM_RIGHT,
  85. IOM_UP | IOM_RIGHT | IOM_DOWN | IOM_LEFT,
  86. IOM_UP | IOM_RIGHT | IOM_LEFT,
  87. IOM_UP | IOM_DOWN | IOM_LEFT,
  88. IOM_RIGHT | IOM_DOWN | IOM_LEFT,
  89. IOM_UP | IOM_RIGHT | IOM_DOWN,
  90. IOM_DOWN,
  91. IOM_RIGHT,
  92. IOM_UP,
  93. IOM_LEFT
  94. };
  95. /* Transition overlays */
  96. /* mh: this array was generated by a GWBASIC program called "trnstns.bas" (incase
  97. they need to be regenerated) */
  98. static int TransitionConnectivityMaskToIndexOffsetMapping[81] =
  99. {-1 ,-1 ,-1 ,-1 ,-1 , 5 ,-1 , 8 ,-1 ,-1 ,-1 , 2 ,-1 ,-1 , 30 , 6 , 18 , 22 ,-1 , 0 ,-1 , 9 , 32 , 13 ,-1 , 24 ,-1 ,-1 ,-1 , 11 ,-1 ,-1 , 17 , 3 , 35 , 27 ,-1 ,-1 , 34 ,-1 ,-1 , 37 , 31 , 38 , 46 , 7 , 28 , 15 , 19 , 39 , 49 , 23 , 47 , 43 ,-1 , 4 ,-1 , 1 , 29 , 21 ,-1 , 12 ,-1 , 10 , 16 , 26 , 33 , 36 , 45 , 14 , 48 , 42 ,-1 , 20 ,-1 , 25 , 44 , 41 ,-1 , 40 ,-1};
  100. #define TIOM_UP1 1
  101. #define TIOM_RIGHT1 3
  102. #define TIOM_DOWN1 9
  103. #define TIOM_LEFT1 27
  104. #define TIOM_UP2 2
  105. #define TIOM_RIGHT2 6
  106. #define TIOM_DOWN2 18
  107. #define TIOM_LEFT2 54
  108. static int TransitionIndexOffsetToConnectivityMaskMapping[50] =
  109. {
  110. TIOM_UP1 + TIOM_DOWN2, // 0
  111. TIOM_RIGHT1 + TIOM_LEFT2,
  112. TIOM_UP2 + TIOM_DOWN1,
  113. TIOM_LEFT1 + TIOM_RIGHT2,
  114. TIOM_UP1 + TIOM_LEFT2,
  115. TIOM_UP2 + TIOM_RIGHT1,
  116. TIOM_DOWN1 + TIOM_RIGHT2,
  117. TIOM_LEFT1 + TIOM_DOWN2,
  118. TIOM_UP1 + TIOM_RIGHT2,
  119. TIOM_RIGHT1 + TIOM_DOWN2,
  120. TIOM_DOWN1 + TIOM_LEFT2, // 10
  121. TIOM_LEFT1 + TIOM_UP2,
  122. TIOM_UP1 + TIOM_RIGHT2 + TIOM_LEFT2,
  123. TIOM_RIGHT1 + TIOM_UP2 + TIOM_DOWN2,
  124. TIOM_DOWN1 + TIOM_RIGHT2 + TIOM_LEFT2,
  125. TIOM_LEFT1 + TIOM_UP2 + TIOM_DOWN2,
  126. TIOM_UP1 + TIOM_DOWN1 + TIOM_LEFT2,
  127. TIOM_RIGHT1 + TIOM_LEFT1 + TIOM_UP2,
  128. TIOM_UP1 + TIOM_DOWN1 + TIOM_RIGHT2,
  129. TIOM_RIGHT1 + TIOM_LEFT1 + TIOM_DOWN2,
  130. TIOM_UP1 + TIOM_DOWN2 + TIOM_LEFT2, // 20
  131. TIOM_RIGHT1 + TIOM_UP2 + TIOM_LEFT2,
  132. TIOM_DOWN1 + TIOM_UP2 + TIOM_RIGHT2,
  133. TIOM_LEFT1 + TIOM_RIGHT2 + TIOM_DOWN2,
  134. TIOM_UP1 + TIOM_RIGHT2 + TIOM_DOWN2,
  135. TIOM_RIGHT1 + TIOM_DOWN2 + TIOM_LEFT2,
  136. TIOM_DOWN1 + TIOM_UP2 + TIOM_LEFT2,
  137. TIOM_LEFT1 + TIOM_UP2 + TIOM_RIGHT2,
  138. TIOM_UP1 + TIOM_LEFT1 + TIOM_DOWN2,
  139. TIOM_UP1 + TIOM_RIGHT1 + TIOM_LEFT2,
  140. TIOM_RIGHT1 + TIOM_DOWN1 + TIOM_UP2, // 30
  141. TIOM_DOWN1 + TIOM_LEFT1 + TIOM_RIGHT2,
  142. TIOM_UP1 + TIOM_RIGHT1 + TIOM_DOWN2,
  143. TIOM_RIGHT1 + TIOM_DOWN1 + TIOM_LEFT2,
  144. TIOM_DOWN1 + TIOM_LEFT1 + TIOM_UP2,
  145. TIOM_UP1 + TIOM_LEFT1 + TIOM_RIGHT2,
  146. TIOM_UP1 + TIOM_RIGHT1 + TIOM_DOWN1 + TIOM_LEFT2,
  147. TIOM_RIGHT1 + TIOM_DOWN1 + TIOM_LEFT1 + TIOM_UP2,
  148. TIOM_UP1 + TIOM_DOWN1 + TIOM_LEFT1 + TIOM_RIGHT2,
  149. TIOM_UP1 + TIOM_RIGHT1 + TIOM_LEFT1 + TIOM_DOWN2,
  150. TIOM_UP1 + TIOM_RIGHT2 + TIOM_DOWN2 + TIOM_LEFT2, // 40
  151. TIOM_RIGHT1 + TIOM_UP2 + TIOM_DOWN2 + TIOM_LEFT2,
  152. TIOM_DOWN1 + TIOM_UP2 + TIOM_RIGHT2 + TIOM_LEFT2,
  153. TIOM_LEFT1 + TIOM_UP2 + TIOM_RIGHT2 + TIOM_DOWN2,
  154. TIOM_UP1 + TIOM_RIGHT1 + TIOM_DOWN2 + TIOM_LEFT2,
  155. TIOM_RIGHT1 + TIOM_DOWN1 + TIOM_UP2 + TIOM_LEFT2,
  156. TIOM_DOWN1 + TIOM_LEFT1 + TIOM_UP2 + TIOM_RIGHT2,
  157. TIOM_UP1 + TIOM_LEFT1 + TIOM_RIGHT2 + TIOM_DOWN2,
  158. TIOM_UP1 + TIOM_DOWN1 + TIOM_RIGHT2 + TIOM_LEFT2,
  159. TIOM_RIGHT1 + TIOM_LEFT1 + TIOM_UP2 + TIOM_DOWN2
  160. };
  161. int texture(Overlays oOverlayType, int indexOffset) {
  162. return ((OverlayTypeToInt(oOverlayType) & 0xffff) << 16) + (indexOffset & 0xffff);
  163. }
  164. Overlays overlayTypeFromTexture(int iTexture) {
  165. return IntToOverlayType((iTexture >> 16) & 0xffff);
  166. }
  167. int indexOffsetFromTexture(int iTexture) {
  168. return (iTexture & 0xffff);
  169. }
  170. static int ConnectivityMaskToTextureMapping(int mask, Overlays currentbrush = INVALID_OVERLAY) {
  171. Overlays tmpType = currentbrush;
  172. if (!((DIRT_ROAD == tmpType) || (PAVED_ROAD == tmpType) || (TWO_LANE_DIRT_ROAD == tmpType) || (DAMAGED_ROAD == tmpType) || (RUNWAY == tmpType) || (OBRIDGE == tmpType) || (DAMAGED_BRIDGE == tmpType))) {
  173. if (INVALID_OVERLAY != currentbrush) {
  174. /* the current brush overlay doesn't support connection, so if the mask contains
  175. the current brush overlay then just return the (only) current brush overlay texture */
  176. int i;
  177. for (i = 0; i < 4; i++) {
  178. Overlays oOverlayType = overlayType(mask, i);
  179. if (currentbrush == oOverlayType) {
  180. int iTexture = texture(currentbrush, 0);
  181. return iTexture;
  182. }
  183. }
  184. }
  185. }
  186. if (RUNWAY == currentbrush) {
  187. /* the runways don't support transitions, so if the mask contains runways then
  188. remove all other overlay types from the mask */
  189. int i;
  190. for (i = 0; i < 4; i++) {
  191. Overlays oOverlayType = overlayType(mask, i);
  192. if (currentbrush == oOverlayType) {
  193. int i;
  194. for (i = 0; i < 4; i++) {
  195. Overlays oOverlayType = overlayType(mask, i);
  196. if (!(RUNWAY == oOverlayType)) {
  197. setOverlayType(mask, i, INVALID_OVERLAY);
  198. }
  199. }
  200. break;
  201. }
  202. }
  203. }
  204. /* here we eliminate overlay types from the mask until there are not more than two */
  205. int i = 0;
  206. while (2 < numberOfOverlayTypes(mask)) {
  207. gosASSERT(4 > i);
  208. if (currentbrush != overlayType(mask, i)) {
  209. setOverlayType(mask, i, INVALID_OVERLAY);
  210. }
  211. i++;
  212. }
  213. int numOverlayTypes = numberOfOverlayTypes(mask);
  214. gosASSERT(2 >= numOverlayTypes);
  215. if (2 == numOverlayTypes) {
  216. Overlays overlayType1 = INVALID_OVERLAY;
  217. Overlays overlayType2 = INVALID_OVERLAY;
  218. int i = 0;
  219. while ((INVALID_OVERLAY == overlayType1) || (INVALID_OVERLAY == overlayType2)) {
  220. gosASSERT(4 > i);
  221. if (INVALID_OVERLAY != overlayType(mask, i)) {
  222. if (INVALID_OVERLAY == overlayType1) {
  223. overlayType1 = overlayType(mask, i);
  224. } else if (overlayType(mask, i) != overlayType1) {
  225. overlayType2 = overlayType(mask, i);
  226. }
  227. }
  228. i++;
  229. }
  230. if (0 == pOverlaysToTransitionMapping) {
  231. pOverlaysToTransitionMapping = new OTMap;
  232. int pair;
  233. pair = (OverlayTypeToInt(DIRT_ROAD) << 16) + OverlayTypeToInt(PAVED_ROAD);
  234. pOverlaysToTransitionMapping->insert(OTMap::value_type(pair, X_DIRT_PAVED));
  235. pair = (OverlayTypeToInt(DIRT_ROAD) << 16) + OverlayTypeToInt(TWO_LANE_DIRT_ROAD);
  236. pOverlaysToTransitionMapping->insert(OTMap::value_type(pair, X_DIRT_2LANEDIRT));
  237. pair = (OverlayTypeToInt(DIRT_ROAD) << 16) + OverlayTypeToInt(DAMAGED_ROAD);
  238. pOverlaysToTransitionMapping->insert(OTMap::value_type(pair, X_DIRT_DAMAGED));
  239. pair = (OverlayTypeToInt(TWO_LANE_DIRT_ROAD) << 16) + OverlayTypeToInt(PAVED_ROAD);
  240. pOverlaysToTransitionMapping->insert(OTMap::value_type(pair, X_2LANEDIRT_PAVED));
  241. pair = (OverlayTypeToInt(DAMAGED_ROAD) << 16) + OverlayTypeToInt(PAVED_ROAD);
  242. pOverlaysToTransitionMapping->insert(OTMap::value_type(pair, X_DAMAGED_PAVED));
  243. pair = (OverlayTypeToInt(TWO_LANE_DIRT_ROAD) << 16) + OverlayTypeToInt(DAMAGED_ROAD);
  244. pOverlaysToTransitionMapping->insert(OTMap::value_type(pair, X_2LANEDIRT_DAMAGED));
  245. pair = (OverlayTypeToInt(PAVED_ROAD) << 16) + OverlayTypeToInt(OBRIDGE);
  246. pOverlaysToTransitionMapping->insert(OTMap::value_type(pair, X_PAVED_ROAD_BRIDGE));
  247. }
  248. OTMap::iterator it;
  249. int pair;
  250. pair = (OverlayTypeToInt(overlayType1) << 16) + OverlayTypeToInt(overlayType2);
  251. it = pOverlaysToTransitionMapping->find(pair);
  252. if (pOverlaysToTransitionMapping->end() == it) {
  253. Overlays swap = overlayType1;
  254. overlayType1 = overlayType2;
  255. overlayType2 = swap;
  256. pair = (OverlayTypeToInt(overlayType1) << 16) + OverlayTypeToInt(overlayType2);
  257. it = pOverlaysToTransitionMapping->find(pair);
  258. }
  259. if (pOverlaysToTransitionMapping->end() == it) {
  260. /* no transition for the pair, eliminate one of the overlay types */
  261. /* here we eliminate overlay types from the mask until there is not more than one */
  262. int i = 0;
  263. while (1 < numberOfOverlayTypes(mask)) {
  264. gosASSERT(4 > i);
  265. if (currentbrush != overlayType(mask, i)) {
  266. setOverlayType(mask, i, INVALID_OVERLAY);
  267. }
  268. i++;
  269. }
  270. numOverlayTypes = numberOfOverlayTypes(mask);
  271. } else {
  272. Overlays iTextureType = (*it).second;
  273. int transitionMask = 0;
  274. int j = 1;
  275. {
  276. int i;
  277. for (i = 0; i < 4; i++) {
  278. Overlays oOverlayType = overlayType(mask, i);
  279. int a = 0;
  280. if (overlayType1 == oOverlayType) {
  281. a = 1;
  282. } else if (overlayType2 == oOverlayType) {
  283. a = 2;
  284. } else {
  285. gosASSERT(INVALID_OVERLAY == oOverlayType);
  286. }
  287. transitionMask += a * j;
  288. j *= 3;
  289. }
  290. }
  291. int indexOffset = TransitionConnectivityMaskToIndexOffsetMapping[transitionMask];
  292. gosASSERT(0 <= indexOffset);
  293. int iTexture = texture(iTextureType, indexOffset);
  294. return iTexture;
  295. }
  296. }
  297. if (1 == numOverlayTypes) {
  298. Overlays oOverlayType = INVALID_OVERLAY;
  299. int i = 0;
  300. while (true) {
  301. gosASSERT(4 > i);
  302. if (INVALID_OVERLAY != overlayType(mask, i)) {
  303. oOverlayType = overlayType(mask, i);
  304. break;
  305. }
  306. i++;
  307. }
  308. int indexOffset = 0;
  309. Overlays tmpType = oOverlayType;
  310. if ((DIRT_ROAD == tmpType) || (PAVED_ROAD == tmpType) || (TWO_LANE_DIRT_ROAD == tmpType) || (DAMAGED_ROAD == tmpType) || (RUNWAY == tmpType) || (OBRIDGE == tmpType) || (DAMAGED_BRIDGE == tmpType)) {
  311. int nonTransitionMask = 0;
  312. if (INVALID_OVERLAY != overlayType(mask, UP)) { nonTransitionMask |= IOM_UP; }
  313. if (INVALID_OVERLAY != overlayType(mask, RIGHT)) { nonTransitionMask |= IOM_RIGHT; }
  314. if (INVALID_OVERLAY != overlayType(mask, DOWN)) { nonTransitionMask |= IOM_DOWN; }
  315. if (INVALID_OVERLAY != overlayType(mask, LEFT)) { nonTransitionMask |= IOM_LEFT; }
  316. gosASSERT(0 != nonTransitionMask);
  317. indexOffset = ConnectivityMaskToIndexOffsetMapping[nonTransitionMask];
  318. }
  319. int iTexture = texture(oOverlayType, indexOffset);
  320. return iTexture;
  321. } else {
  322. gosASSERT(0 == numOverlayTypes);
  323. return texture(INVALID_OVERLAY, 0);
  324. }
  325. gosASSERT(false);
  326. }
  327. static int TextureToConnectivityMaskMapping(int iTexture) {
  328. Overlays oOverlayType = overlayTypeFromTexture(iTexture);
  329. int indexOffset = indexOffsetFromTexture(iTexture);
  330. Overlays tmpType = oOverlayType;
  331. if ((DIRT_ROAD == tmpType) || (PAVED_ROAD == tmpType) || (TWO_LANE_DIRT_ROAD == tmpType) || (DAMAGED_ROAD == tmpType) || (RUNWAY == tmpType) || (OBRIDGE == tmpType) || (DAMAGED_BRIDGE == tmpType)) {
  332. gosASSERT(15 > indexOffset);
  333. int nonTransitionMask = IndexOffsetToConnectivityMaskMapping[indexOffset];
  334. int mask = connectivityMask();
  335. int i;
  336. for (i = 0; i < 4; i++) {
  337. if (0 != (1 & (nonTransitionMask >> i))) {
  338. setOverlayType(mask, i, oOverlayType);
  339. }
  340. }
  341. return mask;
  342. } else if ((X_DIRT_PAVED == tmpType) || (X_DIRT_2LANEDIRT == tmpType) || (X_DIRT_DAMAGED == tmpType) || (X_2LANEDIRT_PAVED == tmpType) || (X_DAMAGED_PAVED == tmpType) || (X_2LANEDIRT_DAMAGED == tmpType) || (X_PAVED_ROAD_BRIDGE == tmpType)) {
  343. if (0 == pTransitionToOverlaysMapping) {
  344. pTransitionToOverlaysMapping = new TOMap;
  345. int pair;
  346. pair = (OverlayTypeToInt(DIRT_ROAD) << 16) + OverlayTypeToInt(PAVED_ROAD);
  347. pTransitionToOverlaysMapping->insert(TOMap::value_type(X_DIRT_PAVED, pair));
  348. pair = (OverlayTypeToInt(DIRT_ROAD) << 16) + OverlayTypeToInt(TWO_LANE_DIRT_ROAD);
  349. pTransitionToOverlaysMapping->insert(TOMap::value_type(X_DIRT_2LANEDIRT, pair));
  350. pair = (OverlayTypeToInt(DIRT_ROAD) << 16) + OverlayTypeToInt(DAMAGED_ROAD);
  351. pTransitionToOverlaysMapping->insert(TOMap::value_type(X_DIRT_DAMAGED, pair));
  352. pair = (OverlayTypeToInt(TWO_LANE_DIRT_ROAD) << 16) + OverlayTypeToInt(PAVED_ROAD);
  353. pTransitionToOverlaysMapping->insert(TOMap::value_type(X_2LANEDIRT_PAVED, pair));
  354. pair = (OverlayTypeToInt(DAMAGED_ROAD) << 16) + OverlayTypeToInt(PAVED_ROAD);
  355. pTransitionToOverlaysMapping->insert(TOMap::value_type(X_DAMAGED_PAVED, pair));
  356. pair = (OverlayTypeToInt(TWO_LANE_DIRT_ROAD) << 16) + OverlayTypeToInt(DAMAGED_ROAD);
  357. pTransitionToOverlaysMapping->insert(TOMap::value_type(X_2LANEDIRT_DAMAGED, pair));
  358. pair = (OverlayTypeToInt(PAVED_ROAD) << 16) + OverlayTypeToInt(OBRIDGE);
  359. pTransitionToOverlaysMapping->insert(TOMap::value_type(X_PAVED_ROAD_BRIDGE, pair));
  360. }
  361. TOMap::iterator it;
  362. it = pTransitionToOverlaysMapping->find(oOverlayType);
  363. if (pTransitionToOverlaysMapping->end() == it) {
  364. gosASSERT(false);
  365. return connectivityMask();
  366. }
  367. int pair = (*it).second;
  368. Overlays overlayType1 = IntToOverlayType((pair >> 16) & 0xffff);
  369. Overlays overlayType2 = IntToOverlayType(pair & 0xffff);
  370. gosASSERT(50 > indexOffset);
  371. int transitionMask = TransitionIndexOffsetToConnectivityMaskMapping[indexOffset];
  372. int mask = connectivityMask();
  373. int i;
  374. int j = 1;
  375. for (i = 0; i < 4; i++) {
  376. int a = (transitionMask % (3 * j)) / j;
  377. if (1 == a) {
  378. setOverlayType(mask, i, overlayType1);
  379. } else if (2 == a) {
  380. setOverlayType(mask, i, overlayType2);
  381. } else {
  382. gosASSERT(0 == a);
  383. }
  384. j *= 3;
  385. }
  386. return mask;
  387. } else {
  388. int mask = connectivityMask();
  389. int i;
  390. for (i = 0; i < 4; i++) {
  391. setOverlayType(mask, i, oOverlayType);
  392. }
  393. return mask;
  394. }
  395. }
  396. static void boundSafeGetOverlay( long tileR, long tileC, Overlays& type, int& Offset )
  397. {
  398. if ((0 > tileR) || (0 > tileC) || (Terrain::realVerticesMapSide <= tileR) || (Terrain::realVerticesMapSide <= tileR))
  399. {
  400. type = INVALID_OVERLAY;
  401. Offset = 0;
  402. return;
  403. }
  404. land->getOverlay(tileR, tileC, type, (unsigned long&)Offset);
  405. }
  406. static int connectivityMaskBasedOnAdjacentTiles( long tileR, long tileC ) {
  407. Overlays connectsAbove = INVALID_OVERLAY;
  408. Overlays connectsToTheRight = INVALID_OVERLAY;
  409. Overlays connectsBelow = INVALID_OVERLAY;
  410. Overlays connectsToTheLeft = INVALID_OVERLAY;
  411. Overlays tmpType;
  412. int tmpOffset;
  413. boundSafeGetOverlay( tileR - 1, tileC, tmpType, tmpOffset );
  414. if ((DIRT_ROAD == tmpType) || (PAVED_ROAD == tmpType) || (TWO_LANE_DIRT_ROAD == tmpType) || (DAMAGED_ROAD == tmpType) || (RUNWAY == tmpType) || (OBRIDGE == tmpType) || (DAMAGED_BRIDGE == tmpType)
  415. || (X_DIRT_PAVED == tmpType) || (X_DIRT_2LANEDIRT == tmpType) || (X_DIRT_DAMAGED == tmpType) || (X_2LANEDIRT_PAVED == tmpType) || (X_DAMAGED_PAVED == tmpType) || (X_2LANEDIRT_DAMAGED == tmpType) || (X_PAVED_ROAD_BRIDGE == tmpType)) {
  416. int iTexture = texture(tmpType, tmpOffset);
  417. int tmpCM = TextureToConnectivityMaskMapping(iTexture);
  418. connectsAbove = overlayType(tmpCM, DOWN);
  419. }
  420. boundSafeGetOverlay( tileR, tileC + 1, tmpType, tmpOffset );
  421. if ((DIRT_ROAD == tmpType) || (PAVED_ROAD == tmpType) || (TWO_LANE_DIRT_ROAD == tmpType) || (DAMAGED_ROAD == tmpType) || (RUNWAY == tmpType) || (OBRIDGE == tmpType) || (DAMAGED_BRIDGE == tmpType)
  422. || (X_DIRT_PAVED == tmpType) || (X_DIRT_2LANEDIRT == tmpType) || (X_DIRT_DAMAGED == tmpType) || (X_2LANEDIRT_PAVED == tmpType) || (X_DAMAGED_PAVED == tmpType) || (X_2LANEDIRT_DAMAGED == tmpType) || (X_PAVED_ROAD_BRIDGE == tmpType)) {
  423. int iTexture = texture(tmpType, tmpOffset);
  424. int tmpCM = TextureToConnectivityMaskMapping(iTexture);
  425. connectsToTheRight = overlayType(tmpCM, LEFT);
  426. }
  427. boundSafeGetOverlay( tileR + 1, tileC, tmpType, tmpOffset );
  428. if ((DIRT_ROAD == tmpType) || (PAVED_ROAD == tmpType) || (TWO_LANE_DIRT_ROAD == tmpType) || (DAMAGED_ROAD == tmpType) || (RUNWAY == tmpType) || (OBRIDGE == tmpType) || (DAMAGED_BRIDGE == tmpType)
  429. || (X_DIRT_PAVED == tmpType) || (X_DIRT_2LANEDIRT == tmpType) || (X_DIRT_DAMAGED == tmpType) || (X_2LANEDIRT_PAVED == tmpType) || (X_DAMAGED_PAVED == tmpType) || (X_2LANEDIRT_DAMAGED == tmpType) || (X_PAVED_ROAD_BRIDGE == tmpType)) {
  430. int iTexture = texture(tmpType, tmpOffset);
  431. int tmpCM = TextureToConnectivityMaskMapping(iTexture);
  432. connectsBelow = overlayType(tmpCM, UP);
  433. }
  434. boundSafeGetOverlay( tileR, tileC - 1, tmpType, tmpOffset );
  435. if ((DIRT_ROAD == tmpType) || (PAVED_ROAD == tmpType) || (TWO_LANE_DIRT_ROAD == tmpType) || (DAMAGED_ROAD == tmpType) || (RUNWAY == tmpType) || (OBRIDGE == tmpType) || (DAMAGED_BRIDGE == tmpType)
  436. || (X_DIRT_PAVED == tmpType) || (X_DIRT_2LANEDIRT == tmpType) || (X_DIRT_DAMAGED == tmpType) || (X_2LANEDIRT_PAVED == tmpType) || (X_DAMAGED_PAVED == tmpType) || (X_2LANEDIRT_DAMAGED == tmpType) || (X_PAVED_ROAD_BRIDGE == tmpType)) {
  437. int iTexture = texture(tmpType, tmpOffset);
  438. int tmpCM = TextureToConnectivityMaskMapping(iTexture);
  439. connectsToTheLeft = overlayType(tmpCM, RIGHT);
  440. }
  441. int iConnectivityMask = connectivityMask(connectsAbove, connectsToTheRight, connectsBelow, connectsToTheLeft);
  442. return iConnectivityMask;
  443. }
  444. bool OverlayBrush::paint( Stuff::Vector3D& worldPos, int screenX, int screenY )
  445. {
  446. long tileC;
  447. long tileR;
  448. land->worldToTile( worldPos, tileR, tileC );
  449. if ( tileR < Terrain::realVerticesMapSide && tileR > -1
  450. && tileC < Terrain::realVerticesMapSide && tileC > -1 )
  451. {
  452. if ((DIRT_ROAD == type) || (PAVED_ROAD == type) || (TWO_LANE_DIRT_ROAD == type) || (DAMAGED_ROAD == type) || (RUNWAY == type) || (OBRIDGE == type) || (DAMAGED_BRIDGE == type)
  453. || (X_DIRT_PAVED == type) || (X_DIRT_2LANEDIRT == type) || (X_DIRT_DAMAGED == type) || (X_2LANEDIRT_PAVED == type) || (X_DAMAGED_PAVED == type) || (X_2LANEDIRT_DAMAGED == type) || (X_PAVED_ROAD_BRIDGE == type)) {
  454. if (-1 == lastTileR) { /* lastTile has not been set yet */
  455. lastTileR = tileR;
  456. lastTileC = tileC;
  457. }
  458. if ((lastTileR != tileR) || (lastTileC != tileC)) {
  459. int brushMotionDirection = -1;
  460. if (lastTileR == tileR) {
  461. if (lastTileC + 1 == tileC) {
  462. brushMotionDirection = RIGHT;
  463. } else if (lastTileC - 1 == tileC) {
  464. brushMotionDirection = LEFT;
  465. }
  466. } else if (lastTileC == tileC) {
  467. if (lastTileR + 1 == tileR) {
  468. brushMotionDirection = DOWN;
  469. } else if (lastTileR - 1 == tileR) {
  470. brushMotionDirection = UP;
  471. }
  472. }
  473. if (-1 != brushMotionDirection) {
  474. /* the brush has been dragged to one of the four adjacent tiles */
  475. pAction->addChangedVertexInfo( tileR, tileC ); // for undo
  476. pAction->addChangedVertexInfo( lastTileR, lastTileC ); // for undo
  477. Overlays tmpType;
  478. int tmpOffset;
  479. /* update last tile */
  480. int lastTileConnectivityMask = connectivityMask();
  481. boundSafeGetOverlay( lastTileR, lastTileC, tmpType, tmpOffset );
  482. int iTexture = texture(tmpType, tmpOffset);
  483. lastTileConnectivityMask = TextureToConnectivityMaskMapping(iTexture);
  484. int tmpCM = connectivityMaskBasedOnAdjacentTiles( lastTileR, lastTileC );
  485. int i;
  486. for (i = 0; i < 4; i++) {
  487. if (overlayType(lastTileConnectivityMask, i) != overlayType(tmpCM, i)) {
  488. setOverlayType(lastTileConnectivityMask, i, INVALID_OVERLAY);
  489. }
  490. }
  491. setOverlayType(lastTileConnectivityMask, brushMotionDirection, type);
  492. int newLastTileTexture = ConnectivityMaskToTextureMapping(lastTileConnectivityMask, type);
  493. Overlays newLastTileType = overlayTypeFromTexture(newLastTileTexture);
  494. int newLastTileIndexOffset = indexOffsetFromTexture(newLastTileTexture);
  495. land->setOverlay( lastTileR, lastTileC, newLastTileType, newLastTileIndexOffset);
  496. /* update current tile */
  497. int tileConnectivityMask = connectivityMaskBasedOnAdjacentTiles( tileR, tileC );
  498. int newTileTexture = ConnectivityMaskToTextureMapping(tileConnectivityMask, type);
  499. Overlays newTileType = overlayTypeFromTexture(newTileTexture);
  500. int newTileIndexOffset = indexOffsetFromTexture(newTileTexture);
  501. land->setOverlay( tileR, tileC, newTileType, newTileIndexOffset);
  502. }
  503. }
  504. } else {
  505. pAction->addChangedVertexInfo( tileR, tileC ); // for undo
  506. land->setOverlay( tileR, tileC, type, offset );
  507. }
  508. } else {
  509. gosASSERT( false );
  510. }
  511. lastTileR = tileR;
  512. lastTileC = tileC;
  513. return true;
  514. }
  515. bool OverlayBrush::beginPaint( )
  516. {
  517. if ( pAction )
  518. {
  519. gosASSERT( false );
  520. }
  521. pAction = new ActionPaintTile;
  522. gosASSERT( pAction );
  523. lastTileR = -1;
  524. lastTileC = -1;
  525. return true;
  526. }
  527. Action* OverlayBrush::endPaint()
  528. {
  529. Action* pRetAction = pAction;
  530. pAction = NULL;
  531. return pRetAction;
  532. }
  533. //*************************************************************************************************
  534. // end of file ( OverlayBrush.cpp )