editor.cpp 10 KB

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