editor.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. /*******************************************************************************************
  2. *
  3. * raylib-extras [ImGui] example - editor
  4. *
  5. * This is a more complex ImGui Integration
  6. * It shows how to build windows on top of 2d and 3d views using a render texture
  7. *
  8. * Copyright (c) 2021 Jeffery Myers
  9. *
  10. ********************************************************************************************/
  11. #include "raylib.h"
  12. #include "raymath.h"
  13. #include "imgui.h"
  14. #include "rlImGui.h"
  15. #include "rlImGuiColors.h"
  16. bool Quit = false;
  17. bool ImGuiDemoOpen = false;
  18. class DocumentWindow
  19. {
  20. public:
  21. bool Open = false;
  22. RenderTexture ViewTexture;
  23. virtual void Setup() = 0;
  24. virtual void Shutdown() = 0;
  25. virtual void Show() = 0;
  26. virtual void Update() = 0;
  27. bool Focused = false;
  28. Rectangle ContentRect = { 0 };
  29. };
  30. class ImageViewerWindow : public DocumentWindow
  31. {
  32. public:
  33. void Setup() override
  34. {
  35. Camera.zoom = 1;
  36. Camera.target.x = 0;
  37. Camera.target.y = 0;
  38. Camera.rotation = 0;
  39. Camera.offset.x = GetScreenWidth() / 2.0f;
  40. Camera.offset.y = GetScreenHeight() / 2.0f;
  41. ViewTexture = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
  42. ImageTexture = LoadTexture("resources/parrots.png");
  43. UpdateRenderTexture();
  44. }
  45. void Show() override
  46. {
  47. ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
  48. ImGui::SetNextWindowSizeConstraints(ImVec2(400, 400), ImVec2((float)GetScreenWidth(), (float)GetScreenHeight()));
  49. Focused = false;
  50. if (ImGui::Begin("Image Viewer", &Open, ImGuiWindowFlags_NoScrollbar))
  51. {
  52. // save off the screen space content rectangle
  53. ContentRect = { ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMin().x, ImGui::GetWindowPos().y + ImGui::GetWindowContentRegionMin().y, ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y };
  54. Focused = ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows);
  55. ImVec2 size = ImGui::GetContentRegionAvail();
  56. // center the scratch pad in the view
  57. Rectangle viewRect = { 0 };
  58. viewRect.x = ViewTexture.texture.width / 2 - size.x / 2;
  59. viewRect.y = ViewTexture.texture.height / 2 - size.y / 2;
  60. viewRect.width = size.x;
  61. viewRect.height = -size.y;
  62. if (ImGui::BeginChild("Toolbar", ImVec2(ImGui::GetContentRegionAvail().x, 25)))
  63. {
  64. ImGui::SetCursorPosX(2);
  65. ImGui::SetCursorPosY(3);
  66. if (ImGui::Button("None"))
  67. {
  68. CurrentToolMode = ToolMode::None;
  69. }
  70. ImGui::SameLine();
  71. if (ImGui::Button("Move"))
  72. {
  73. CurrentToolMode = ToolMode::Move;
  74. }
  75. ImGui::SameLine();
  76. switch (CurrentToolMode)
  77. {
  78. case ToolMode::None:
  79. ImGui::TextUnformatted("No Tool");
  80. break;
  81. case ToolMode::Move:
  82. ImGui::TextUnformatted("Move Tool");
  83. break;
  84. default:
  85. break;
  86. }
  87. ImGui::SameLine();
  88. ImGui::TextUnformatted(TextFormat("camera target X%f Y%f", Camera.target.x, Camera.target.y));
  89. ImGui::EndChild();
  90. }
  91. rlImGuiImageRect(&ViewTexture.texture, (int)size.x, (int)size.y, viewRect);
  92. }
  93. ImGui::End();
  94. ImGui::PopStyleVar();
  95. }
  96. void Update() override
  97. {
  98. if (!Open)
  99. return;
  100. if (IsWindowResized())
  101. {
  102. UnloadRenderTexture(ViewTexture);
  103. ViewTexture = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
  104. Camera.offset.x = GetScreenWidth() / 2.0f;
  105. Camera.offset.y = GetScreenHeight() / 2.0f;
  106. }
  107. Vector2 mousePos = GetMousePosition();
  108. if (Focused)
  109. {
  110. if (CurrentToolMode == ToolMode::Move)
  111. {
  112. // only do this tool when the mouse is in the content area of the window
  113. if (IsMouseButtonDown(0) && CheckCollisionPointRec(mousePos, ContentRect))
  114. {
  115. if (!Dragging)
  116. {
  117. LastMousePos = mousePos;
  118. LastTarget = Camera.target;
  119. }
  120. Dragging = true;
  121. Vector2 mouseDelta = Vector2Subtract(LastMousePos, mousePos);
  122. mouseDelta.x /= Camera.zoom;
  123. mouseDelta.y /= Camera.zoom;
  124. Camera.target = Vector2Add(LastTarget, mouseDelta);
  125. DirtyScene = true;
  126. }
  127. else
  128. {
  129. Dragging = false;
  130. }
  131. }
  132. }
  133. else
  134. {
  135. Dragging = false;
  136. }
  137. if (DirtyScene)
  138. {
  139. DirtyScene = false;
  140. UpdateRenderTexture();
  141. }
  142. }
  143. Texture ImageTexture;
  144. Camera2D Camera = { 0 };
  145. Vector2 LastMousePos = { 0 };
  146. Vector2 LastTarget = { 0 };
  147. bool Dragging = false;
  148. bool DirtyScene = false;
  149. enum class ToolMode
  150. {
  151. None,
  152. Move,
  153. };
  154. ToolMode CurrentToolMode = ToolMode::None;
  155. void UpdateRenderTexture()
  156. {
  157. BeginTextureMode(ViewTexture);
  158. ClearBackground(BLUE);
  159. BeginMode2D(Camera);
  160. DrawTexture(ImageTexture, ImageTexture.width / -2, ImageTexture.height / -2, WHITE);
  161. EndMode2D();
  162. EndTextureMode();
  163. }
  164. void Shutdown() override
  165. {
  166. UnloadRenderTexture(ViewTexture);
  167. UnloadTexture(ImageTexture);
  168. }
  169. };
  170. class SceneViewWindow : public DocumentWindow
  171. {
  172. public:
  173. Camera3D Camera = { 0 };
  174. void Setup() override
  175. {
  176. ViewTexture = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
  177. Camera.fovy = 45;
  178. Camera.up.y = 1;
  179. Camera.position.y = 3;
  180. Camera.position.z = -25;
  181. Image img = GenImageChecked(256, 256, 32, 32, DARKGRAY, WHITE);
  182. GridTexture = LoadTextureFromImage(img);
  183. UnloadImage(img);
  184. GenTextureMipmaps(&GridTexture);
  185. SetTextureFilter(GridTexture, TEXTURE_FILTER_ANISOTROPIC_16X);
  186. SetTextureWrap(GridTexture, TEXTURE_WRAP_CLAMP);
  187. }
  188. void Shutdown() override
  189. {
  190. UnloadRenderTexture(ViewTexture);
  191. UnloadTexture(GridTexture);
  192. }
  193. void Show() override
  194. {
  195. ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
  196. ImGui::SetNextWindowSizeConstraints(ImVec2(400, 400), ImVec2((float)GetScreenWidth(), (float)GetScreenHeight()));
  197. if (ImGui::Begin("3D View", &Open, ImGuiWindowFlags_NoScrollbar))
  198. {
  199. Focused = ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows);
  200. ImVec2 size = ImGui::GetContentRegionAvail();
  201. Rectangle viewRect = { 0 };
  202. viewRect.x = ViewTexture.texture.width / 2 - size.x / 2;
  203. viewRect.y = ViewTexture.texture.height / 2 - size.y / 2;
  204. viewRect.width = size.x;
  205. viewRect.height = -size.y;
  206. // draw the view
  207. rlImGuiImageRect(&ViewTexture.texture, (int)size.x, (int)size.y, viewRect);
  208. }
  209. ImGui::End();
  210. ImGui::PopStyleVar();
  211. }
  212. void Update() override
  213. {
  214. if (!Open)
  215. return;
  216. if (IsWindowResized())
  217. {
  218. UnloadRenderTexture(ViewTexture);
  219. ViewTexture = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
  220. }
  221. float period = 10;
  222. float magnitude = 25;
  223. Camera.position.x = (float)(sinf((float)GetTime() / period) * magnitude);
  224. BeginTextureMode(ViewTexture);
  225. ClearBackground(SKYBLUE);
  226. BeginMode3D(Camera);
  227. // grid of cube trees on a plane to make a "world"
  228. DrawPlane(Vector3{ 0, 0, 0 }, Vector2{ 50, 50 }, BEIGE); // simple world plane
  229. float spacing = 4;
  230. int count = 5;
  231. for (float x = -count * spacing; x <= count * spacing; x += spacing)
  232. {
  233. for (float z = -count * spacing; z <= count * spacing; z += spacing)
  234. {
  235. Vector3 pos = { x, 0.5f, z };
  236. Vector3 min = { x - 0.5f,0,z - 0.5f };
  237. Vector3 max = { x + 0.5f,1,z + 0.5f };
  238. DrawCube(Vector3{ x, 1.5f, z }, 1, 1, 1, GREEN);
  239. DrawCube(Vector3{ x, 0.5f, z }, 0.25f, 1, 0.25f, BROWN);
  240. }
  241. }
  242. EndMode3D();
  243. EndTextureMode();
  244. }
  245. Texture2D GridTexture = { 0 };
  246. };
  247. ImageViewerWindow ImageViewer;
  248. SceneViewWindow SceneView;
  249. void DoMainMenu()
  250. {
  251. if (ImGui::BeginMainMenuBar())
  252. {
  253. if (ImGui::BeginMenu("File"))
  254. {
  255. if (ImGui::MenuItem("Exit"))
  256. Quit = true;
  257. ImGui::EndMenu();
  258. }
  259. if (ImGui::BeginMenu("Window"))
  260. {
  261. ImGui::MenuItem("ImGui Demo", nullptr, &ImGuiDemoOpen);
  262. ImGui::MenuItem("Image Viewer", nullptr, &ImageViewer.Open);
  263. ImGui::MenuItem("3D View", nullptr, &SceneView.Open);
  264. ImGui::EndMenu();
  265. }
  266. ImGui::EndMainMenuBar();
  267. }
  268. }
  269. int main(int argc, char* argv[])
  270. {
  271. // Initialization
  272. //--------------------------------------------------------------------------------------
  273. int screenWidth = 1900;
  274. int screenHeight = 900;
  275. SetConfigFlags(FLAG_MSAA_4X_HINT | FLAG_VSYNC_HINT);
  276. InitWindow(screenWidth, screenHeight, "raylib-Extras [ImGui] example - ImGui Demo");
  277. SetTargetFPS(144);
  278. rlImGuiSetup(true);
  279. ImGui::GetIO().ConfigWindowsMoveFromTitleBarOnly = true;
  280. ImageViewer.Setup();
  281. ImageViewer.Open = true;
  282. SceneView.Setup();
  283. SceneView.Open = true;
  284. // Main game loop
  285. while (!WindowShouldClose() && !Quit) // Detect window close button or ESC key
  286. {
  287. ImageViewer.Update();
  288. SceneView.Update();
  289. BeginDrawing();
  290. ClearBackground(DARKGRAY);
  291. rlImGuiBegin();
  292. DoMainMenu();
  293. if (ImGuiDemoOpen)
  294. ImGui::ShowDemoWindow(&ImGuiDemoOpen);
  295. if (ImageViewer.Open)
  296. ImageViewer.Show();
  297. if (SceneView.Open)
  298. SceneView.Show();
  299. rlImGuiEnd();
  300. EndDrawing();
  301. //----------------------------------------------------------------------------------
  302. }
  303. rlImGuiShutdown();
  304. ImageViewer.Shutdown();
  305. SceneView.Shutdown();
  306. // De-Initialization
  307. //--------------------------------------------------------------------------------------
  308. CloseWindow(); // Close window and OpenGL context
  309. //--------------------------------------------------------------------------------------
  310. return 0;
  311. }