isometricGameEditor.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. #include <containers/isometricGame/isometricGameEditor.h>
  2. #include <glui/glui.h>
  3. static int blocksCount = 17;
  4. bool IsometricGameEditor::redstoneWire(int type)
  5. {
  6. return type == IsometricGameEditor::Blocks::redstone ||
  7. type == IsometricGameEditor::Blocks::trapdor ||
  8. type == IsometricGameEditor::Blocks::redstoneTorch ||
  9. type == IsometricGameEditor::Blocks::redstoneBlock ||
  10. type == IsometricGameEditor::Blocks::lever;
  11. }
  12. bool IsometricGameEditor::pointInBox(glm::vec2 p, glm::vec4 box)
  13. {
  14. if
  15. (
  16. (p.x >= box.x && p.x <= (box.x + box.z)) &&
  17. (p.y >= box.y && p.y <= (box.y + box.w))
  18. )
  19. {
  20. return true;
  21. }
  22. else
  23. {
  24. return false;
  25. }
  26. }
  27. bool IsometricGameEditor::canPlaceRedstoneOn(int type)
  28. {
  29. return (type >= IsometricGameEditor::Blocks::clay &&
  30. type <= IsometricGameEditor::Blocks::woddenPlank)
  31. || type == IsometricGameEditor::Blocks::redstoneBlock;
  32. }
  33. bool IsometricGameEditor::create(RequestedContainerInfo &requestedInfo, pika::StaticString<256> commandLineArgument)
  34. {
  35. renderer.create(requestedInfo.requestedFBO.fbo);
  36. tiles = pika::gl2d::loadTextureWithPixelPadding(PIKA_RESOURCES_PATH "iso/tiles/Isometric-Tiles.png", requestedInfo, 32, true);
  37. shadow = pika::gl2d::loadTexture(PIKA_RESOURCES_PATH "iso/tiles/shadow.png", requestedInfo, 32, true);
  38. tilesAtlas = gl2d::TextureAtlasPadding(16, 8, tiles.GetSize().x, tiles.GetSize().y);
  39. //fileChanged.setFile(mapFile.c_str());
  40. loadedLevel.setInfo("Level", PIKA_RESOURCES_PATH "iso/maps", {".isomap"});
  41. bool created = 0;
  42. if (commandLineArgument.size() > 0)
  43. {
  44. //editor.loadFromFile(renderer, commandLineArgument.to_string(), requestedInfo);
  45. size_t s = 0;
  46. pika::strlcpy(loadedLevel.file, commandLineArgument.to_string(), sizeof(loadedLevel.file));
  47. glm::ivec3 mapSize = {};
  48. if (requestedInfo.readEntireFileBinary(commandLineArgument.to_string(), &mapSize, sizeof(mapSize), 0))
  49. {
  50. if (requestedInfo.getFileSizeBinary(commandLineArgument.to_string().c_str(), s))
  51. {
  52. if (s == mapSize.x * mapSize.y * mapSize.z * sizeof(Block) + sizeof(mapSize))
  53. {
  54. created = 1;
  55. map.init(mapSize);
  56. requestedInfo.readEntireFileBinary(commandLineArgument.to_string().c_str(),
  57. map.mapData.data(), mapSize.x * mapSize.y * mapSize.z * sizeof(Block), sizeof(mapSize));
  58. }
  59. }
  60. }
  61. }
  62. if (!created)
  63. {
  64. map.init({10,10,10});
  65. for (int i = 0; i < 10; i++)
  66. for (int j = 0; j < 10; j++)
  67. {
  68. map.setSafe({i,0,j}, 1, 0);
  69. }
  70. map.setSafe({5,1,5}, 6, 0);
  71. map.setSafe({5,2,5}, 6, 0);
  72. }
  73. newMapSize = map.size;
  74. return true;
  75. }
  76. bool IsometricGameEditor::update(pika::Input input, pika::WindowState windowState, RequestedContainerInfo &requestedInfo)
  77. {
  78. #pragma region clear stuff
  79. glClear(GL_COLOR_BUFFER_BIT);
  80. renderer.updateWindowMetrics(windowState.windowW, windowState.windowH);
  81. #pragma endregion
  82. float size = 100;
  83. #pragma region move
  84. float cameraSpeed = input.deltaTime * size * 2.f;
  85. if (input.buttons[pika::Button::A].held())
  86. {
  87. renderer.currentCamera.position.x -= cameraSpeed;
  88. }
  89. if (input.buttons[pika::Button::D].held())
  90. {
  91. renderer.currentCamera.position.x += cameraSpeed;
  92. }
  93. if (input.buttons[pika::Button::W].held())
  94. {
  95. renderer.currentCamera.position.y -= cameraSpeed;
  96. }
  97. if (input.buttons[pika::Button::S].held())
  98. {
  99. renderer.currentCamera.position.y += cameraSpeed;
  100. }
  101. #pragma endregion
  102. auto calculateBlockPos = [size](glm::ivec3 in)
  103. {
  104. glm::vec2 position = {};
  105. position += glm::vec2(-size / 2.f, size / 4.f) * float(in.x);
  106. position += glm::vec2(size / 2.f, size / 4.f) * float(in.z);
  107. position += glm::vec2(0, -size / 2.f) * float(in.y);
  108. return position;
  109. };
  110. glm::ivec3 currentSelectedBlockDelete{-1};
  111. glm::ivec3 currentSelectedBlockPlace{-1};
  112. auto viewRect = renderer.getViewRect();
  113. auto lerp = [](auto a, auto b, auto c)
  114. {
  115. return a * (1.f - c) + b * c;
  116. };
  117. glm::vec2 blockPositionScreen = lerp(glm::vec2(viewRect.x, viewRect.y),
  118. glm::vec2(viewRect.x + viewRect.z, viewRect.y + viewRect.w),
  119. glm::vec2(input.mouseX, input.mouseY) / glm::vec2(windowState.windowW, windowState.windowH));
  120. for (int y = 0; y < map.size.y; y++)
  121. for (int z = 0; z < map.size.z; z++)
  122. for (int x = 0; x < map.size.x; x++)
  123. {
  124. auto checkPointInBox = [&](int x, int y, int z, bool reverse = 0)
  125. {
  126. auto b = map.getSafe({x,y,z});
  127. if (!b) { return false; }
  128. if ((b->get().x != 0 && !reverse)
  129. || (b->get().x == 0 && reverse)
  130. )
  131. {
  132. glm::vec2 position = calculateBlockPos({x,y,z});
  133. glm::vec4 box = renderer.toScreen({position, size, size});
  134. //todo new functon
  135. box.x += 1;
  136. box.x /= 2.f;
  137. box.x *= renderer.windowW;
  138. box.y *= -1;
  139. box.y += 1;
  140. box.y /= 2.f;
  141. box.y *= renderer.windowH;
  142. box.z += 1;
  143. box.z /= 2.f;
  144. box.z *= renderer.windowW;
  145. box.w *= -1;
  146. box.w += 1;
  147. box.w /= 2.f;
  148. box.w *= renderer.windowH;
  149. box.z = box.z - box.x;
  150. box.w = box.w - box.y;
  151. if (pointInBox(glm::vec2(input.mouseX, input.mouseY), box))
  152. {
  153. return true;
  154. }
  155. }
  156. return false;
  157. };
  158. if (checkPointInBox(x,y,z))
  159. {
  160. currentSelectedBlockDelete = {x,y,z};
  161. if (checkPointInBox(x + 1, y, z, true))
  162. {
  163. currentSelectedBlockPlace = {x + 1,y,z};
  164. }
  165. if (checkPointInBox(x, y + 1, z, true))
  166. {
  167. currentSelectedBlockPlace = {x,y + 1,z};
  168. }
  169. if (checkPointInBox(x, y, z + 1, true))
  170. {
  171. currentSelectedBlockPlace = {x,y,z + 1};
  172. }
  173. }
  174. }
  175. for (int y = 0; y < map.size.y; y++)
  176. for (int z = 0; z < map.size.z; z++)
  177. for (int x = 0; x < map.size.x; x++)
  178. {
  179. auto b = map.getSafe({x,y,z});
  180. if (b->get().x != 0)
  181. {
  182. glm::vec2 position = calculateBlockPos({x,y,z});
  183. glm::vec4 color = Colors_White;
  184. if (b->get().x == Blocks::redstone)
  185. {
  186. color = glm::vec4(0.8, 0.2, 0.2, 1.0);
  187. }
  188. if (b->get().x == Blocks::redstone || b->get().x == Blocks::lever
  189. || b->get().x == Blocks::redstoneTorch
  190. )
  191. {
  192. auto cr = glm::vec4(0.8, 0.2, 0.2, 1.0);
  193. auto b2 = map.getSafe({x,y,z - 1});
  194. if (b2 && redstoneWire(b2->type))
  195. {
  196. renderer.renderRectangle({position,size,size}, tiles, cr, {}, 0,
  197. tilesAtlas.get(Blocks::redstone, 1));
  198. }
  199. b2 = map.getSafe({x - 1,y,z});
  200. if (b2 && redstoneWire(b2->type))
  201. {
  202. renderer.renderRectangle({position,size,size}, tiles, cr, {}, 0,
  203. tilesAtlas.get(Blocks::redstone, 2));
  204. }
  205. b2 = map.getSafe({x + 1,y,z});
  206. if (b2 && redstoneWire(b2->type))
  207. {
  208. renderer.renderRectangle({position,size,size}, tiles, cr, {}, 0,
  209. tilesAtlas.get(Blocks::redstone, 3));
  210. }
  211. b2 = map.getSafe({x,y,z + 1});
  212. if (b2 && redstoneWire(b2->type))
  213. {
  214. renderer.renderRectangle({position,size,size}, tiles, cr, {}, 0,
  215. tilesAtlas.get(Blocks::redstone, 4));
  216. }
  217. //redstone on wall
  218. b2 = map.getSafe({x - 1,y + 1,z});
  219. if (b2 && redstoneWire(b2->type))
  220. {
  221. renderer.renderRectangle({position,size,size}, tiles, cr, {}, 0,
  222. tilesAtlas.get(Blocks::redstone, 2));
  223. renderer.renderRectangle({position,size,size}, tiles, cr, {}, 0,
  224. tilesAtlas.get(Blocks::redstone, 5));
  225. }
  226. b2 = map.getSafe({x,y + 1,z - 1});
  227. if (b2 && redstoneWire(b2->type))
  228. {
  229. renderer.renderRectangle({position,size,size}, tiles, cr, {}, 0,
  230. tilesAtlas.get(Blocks::redstone, 1));
  231. renderer.renderRectangle({position,size,size}, tiles, cr, {}, 0,
  232. tilesAtlas.get(Blocks::redstone, 6));
  233. }
  234. //redstone down
  235. b2 = map.getSafe({x + 1,y - 1,z});
  236. if (b2 && redstoneWire(b2->type))
  237. {
  238. renderer.renderRectangle({position,size,size}, tiles, cr, {}, 0,
  239. tilesAtlas.get(Blocks::redstone, 3));
  240. }
  241. b2 = map.getSafe({x,y - 1,z + 1});
  242. if (b2 && redstoneWire(b2->type))
  243. {
  244. renderer.renderRectangle({position,size,size}, tiles, cr, {}, 0,
  245. tilesAtlas.get(Blocks::redstone, 4));
  246. }
  247. }
  248. renderer.renderRectangle({position,size,size}, tiles, color, {}, 0,
  249. tilesAtlas.get(b->get().x, b->get().y));
  250. int advance = 1;
  251. for (int y2 = y + 2; y2 < map.size.y; y2++)
  252. {
  253. advance++;
  254. auto b2 = map.getSafe({x,y2,z});
  255. if (b2 && b2->get().x != 0 && b->get().x != Blocks::redstone
  256. && b->get().x != Blocks::lever)
  257. {
  258. renderer.renderRectangle({position,size,size}, shadow,
  259. {1,1,1,1.f/advance}
  260. );
  261. break;
  262. }
  263. }
  264. }
  265. if (currentSelectedBlockDelete == glm::ivec3{x, y, z})
  266. {
  267. glm::vec2 position = calculateBlockPos({x,y,z});
  268. renderer.renderRectangle({position,size,size}, tiles, Colors_White, {}, 0,
  269. tilesAtlas.get(0, 1));
  270. }
  271. if (currentSelectedBlockPlace == glm::ivec3{x, y, z})
  272. {
  273. glm::vec2 position = calculateBlockPos({x,y,z});
  274. renderer.renderRectangle({position,size,size}, tiles, {0.1,0.1,0.1,0.1}, {}, 0,
  275. tilesAtlas.get(0, 1));
  276. }
  277. if (blockSelector == glm::ivec3{x, y, z})
  278. {
  279. glm::vec2 position = calculateBlockPos({x,y,z});
  280. renderer.renderRectangle({position,size,size}, tiles, {0.5,0.9,0.1,0.9}, {}, 0,
  281. tilesAtlas.get(0, 1));
  282. }
  283. }
  284. if (currentSelectedBlockDelete.x > -1)
  285. {
  286. if (
  287. input.lMouse.pressed()
  288. )
  289. {
  290. auto b = map.getSafe(currentSelectedBlockDelete);
  291. if (b)
  292. {
  293. b->set(0, 0);
  294. }
  295. }
  296. }
  297. if (currentSelectedBlockPlace.x > -1)
  298. {
  299. if (
  300. input.rMouse.pressed()
  301. )
  302. {
  303. auto b = map.getSafe(currentSelectedBlockPlace);
  304. if (b)
  305. {
  306. if (currentBlock == Blocks::redstone || currentBlock == Blocks::trapdor)
  307. {
  308. auto b2 = map.getSafe(currentSelectedBlockPlace - glm::ivec3(0,1,0));
  309. if (b2 && canPlaceRedstoneOn(b2->get().x))
  310. {
  311. b->set(currentBlock, 0);
  312. }
  313. }
  314. else
  315. {
  316. b->set(currentBlock, 0);
  317. }
  318. }
  319. }
  320. }
  321. renderer.flush();
  322. ImGui::Begin("camera editor");
  323. ImGui::DragFloat2("camera", &renderer.currentCamera.position[0], 2, -3200, 3200);
  324. ImGui::DragInt3("block selector", &blockSelector[0], 1, 0);
  325. {
  326. auto uv1 = tilesAtlas.get(currentBlock, 0);
  327. ImGui::Image((void *)(intptr_t)tiles.id,
  328. {35,35}, {uv1.x, uv1.y}, {uv1.z, uv1.w});
  329. }
  330. ImGui::NewLine();
  331. {
  332. for (int mCount = 0; mCount < blocksCount; mCount++)
  333. {
  334. auto uv1 = tilesAtlas.get(mCount, 0);
  335. ImGui::PushID(mCount);
  336. if (ImGui::ImageButton((void *)(intptr_t)tiles.id,
  337. {35,35}, {uv1.x, uv1.y}, {uv1.z, uv1.w}))
  338. {
  339. currentBlock = mCount;
  340. }
  341. ImGui::PopID();
  342. if ((mCount + 1) % 5 != 0)
  343. {
  344. ImGui::SameLine();
  345. }
  346. }
  347. }
  348. if (input.buttons[pika::Button::Z].pressed()) { currentBlock--; }
  349. if (input.buttons[pika::Button::X].pressed()) { currentBlock++; }
  350. currentBlock = glm::clamp(currentBlock, 0, blocksCount-1);
  351. ImGui::NewLine();
  352. //ImGui::DragInt3("Cursor pos", &currentSelectedBlockDelete[0], 1);
  353. //currentSelectedBlock = glm::clamp(currentSelectedBlock, glm::ivec3{0}, map.size - glm::ivec3(1));
  354. ImGui::NewLine();
  355. ImGui::DragInt3("NewMapSize", &newMapSize[0]);
  356. if (ImGui::Button("Resize Map"))
  357. {
  358. Map newMap;
  359. newMap.init(newMapSize);
  360. for (int x = 0; x < map.size.x; x++)
  361. for (int y = 0; y < map.size.y; y++)
  362. for (int z = 0; z < map.size.z; z++)
  363. {
  364. auto b = map.getSafe({x,y,z});
  365. auto b2 = newMap.getSafe({x,y,z});
  366. if (b2)
  367. {
  368. *b2 = *b;
  369. }
  370. }
  371. map = std::move(newMap);
  372. }
  373. if (ImGui::Button("Replace floor"))
  374. {
  375. for (int x = 0; x < map.size.x; x++)
  376. for (int z = 0; z < map.size.z; z++)
  377. {
  378. auto b = map.getSafe({x,0,z});
  379. b->set(currentBlock, 0);
  380. }
  381. }
  382. ImGui::NewLine();
  383. loadedLevel.run(requestedInfo.requestedImguiIds);
  384. if (ImGui::Button("save map"))
  385. {
  386. if (requestedInfo.writeEntireFileBinary(loadedLevel.file, &map.size, sizeof(map.size)))
  387. {
  388. requestedInfo.appendFileBinary(loadedLevel.file, map.mapData.data(),
  389. sizeof(Block) * map.mapData.size());
  390. //toto log errors
  391. }
  392. }
  393. ImGui::NewLine();
  394. ImGui::End();
  395. return true;
  396. }
  397. void IsometricGameEditor::destruct(RequestedContainerInfo &requestedInfo)
  398. {
  399. renderer.cleanup();
  400. }