Browse Source

Add basic window creation functionality

Patrick-Christopher Mattulat 1 tuần trước cách đây
mục cha
commit
df8f7c3d91

+ 2 - 0
CMakeLists.txt

@@ -48,6 +48,7 @@ endif ()
 set(ATLANTIS_CORE_SOURCES
         ${CMAKE_CURRENT_SOURCE_DIR}/source/core/StatusCodeOk.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/core/StatusCodeWindowApiLoadingFailed.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/core/StatusCodeWindowCreationFailed.cpp
 )
 
 ################################
@@ -69,6 +70,7 @@ target_link_libraries(${MODULE_NAME_CORE} PUBLIC
 set(ATLANTIS_CORE_TEST_SOURCES
         ${CMAKE_CURRENT_SOURCE_DIR}/test/core/StatusCodeOkTest.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/core/StatusCodeWindowApiLoadingFailedTest.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/test/core/StatusCodeWindowCreationFailedTest.cpp
 )
 
 ################################

+ 1 - 1
doc/coding-guidelines.md

@@ -22,7 +22,7 @@ The following naming conventions must be met for code contribution:
 1. Class names follow the CamelCase convention, where the first letter is an upper case letter.
 2. Class methods follow the CamelCase convention, where the first letter is a lower case letter, when the method is public.
 3. Class methods follow the CamelCase convention, where the first letter is an underscore letter, followed by a lower case letter, when the method is private.
-4. Method and function parameter follow the CamelCase convention, where the first letter is an underscore letter, followed by a lower case letter.
+4. Method and function parameter follow the camelCase convention, where the first letter is an underscore letter, followed by a lower case letter.
 5. Private class members follow the CamelCase convention, where the first letter starts with a lower case letter.
 6. Header or source files of classes must meet the same naming convention as for class names, followed by the class extension (.cpp for source files, .hpp for header files).
 7. Class methods with a return type other than void must be declared with __[[nodiscard]]__.

+ 23 - 0
include/core/StatusCodeWindowCreationFailed.hpp

@@ -0,0 +1,23 @@
+/*
+ * author: Patrick-Christopher Mattulat
+ * e-mail: webmaster@lynarstudios.com
+ */
+
+#ifndef LS_ATLANTIS_ENGINE_CORE_STATUS_CODE_WINDOW_CREATION_FAILED_HPP
+#define LS_ATLANTIS_ENGINE_CORE_STATUS_CODE_WINDOW_CREATION_FAILED_HPP
+
+#include <Export.hpp>
+#include <interface/AStatusCode.hpp>
+
+namespace ls::atlantis::core
+{
+  class LS_ATLANTIS_DYNAMIC_GOAL StatusCodeWindowCreationFailed : public ls::atlantis::interfaces::AStatusCode
+  {
+    public:
+
+      StatusCodeWindowCreationFailed();
+      ~StatusCodeWindowCreationFailed() override;
+  };
+}
+
+#endif

+ 2 - 1
include/core/StatusCodes.hpp

@@ -11,7 +11,8 @@ namespace ls::atlantis::core
   enum StatusCodes
   {
     OK = 1,
-    WINDOW_API_LOADING_FAILED = 2
+    WINDOW_API_LOADING_FAILED = 2,
+    WINDOW_CREATION_FAILED = 3
   };
 }
 

+ 2 - 0
include/interface/ISdlApi.hpp

@@ -18,6 +18,8 @@ namespace ls::atlantis::interfaces
       ISdlApi();
       virtual ~ISdlApi();
 
+      virtual SDL_Window *CreateWindow(const char *_title, int _width, int _height, SDL_WindowFlags _flags) = 0;
+      virtual void DestroyWindow(SDL_Window *_window) = 0;
       virtual bool Init(SDL_InitFlags flags) = 0;
       virtual void Quit() = 0;
   };

+ 2 - 0
include/window/SdlApi.hpp

@@ -18,6 +18,8 @@ namespace ls::atlantis::window
       SdlApi();
       ~SdlApi() override;
 
+      SDL_Window *CreateWindow(const char *_title, int _width, int _height, SDL_WindowFlags _flags) override;
+      void DestroyWindow(SDL_Window *_window) override;
       bool Init(SDL_InitFlags flags) override;
       void Quit() override;
   };

+ 4 - 2
include/window/SdlWindowApi.hpp

@@ -10,6 +10,7 @@
 #include <interface/AStatusCode.hpp>
 #include <interface/ISdlApi.hpp>
 #include <interface/IWindowApi.hpp>
+#include <functional>
 #include <memory>
 
 namespace ls::atlantis::window
@@ -26,10 +27,11 @@ namespace ls::atlantis::window
 
     private:
 
-      static ::std::shared_ptr<ls::atlantis::interfaces::AStatusCode> _createWindow();
-      ::std::shared_ptr<ls::atlantis::interfaces::AStatusCode> _initApi();
+      [[nodiscard]] ::std::shared_ptr<ls::atlantis::interfaces::AStatusCode> _createWindow();
+      [[nodiscard]] ::std::shared_ptr<ls::atlantis::interfaces::AStatusCode> _initApi() const;
 
       ::std::shared_ptr<ls::atlantis::interfaces::ISdlApi> sdlApi{};
+      ::std::unique_ptr<SDL_Window, ::std::function<void(SDL_Window *)>> window{nullptr, [](SDL_Window *) {}};
   };
 }
 

+ 16 - 0
source/core/StatusCodeWindowCreationFailed.cpp

@@ -0,0 +1,16 @@
+/*
+ * author: Patrick-Christopher Mattulat
+ * e-mail: webmaster@lynarstudios.com
+ */
+
+#include <core/StatusCodeWindowCreationFailed.hpp>
+#include <core/StatusCodes.hpp>
+
+using ls::atlantis::core::StatusCodes;
+using ls::atlantis::interfaces::AStatusCode;
+using ls::atlantis::core::StatusCodeWindowCreationFailed;
+
+StatusCodeWindowCreationFailed::StatusCodeWindowCreationFailed() : AStatusCode(StatusCodes::WINDOW_CREATION_FAILED, "window creation failed")
+{}
+
+StatusCodeWindowCreationFailed::~StatusCodeWindowCreationFailed() = default;

+ 10 - 0
source/window/SdlApi.cpp

@@ -11,6 +11,16 @@ SdlApi::SdlApi() = default;
 
 SdlApi::~SdlApi() = default;
 
+SDL_Window *SdlApi::CreateWindow(const char *_title, const int _width, const int _height, const SDL_WindowFlags _flags)
+{
+  return SDL_CreateWindow(_title, _width, _height, _flags);
+}
+
+void SdlApi::DestroyWindow(SDL_Window *_window)
+{
+  SDL_DestroyWindow(_window);
+}
+
 bool SdlApi::Init(const SDL_InitFlags flags)
 {
   return SDL_Init(flags);

+ 21 - 3
source/window/SdlWindowApi.cpp

@@ -6,12 +6,14 @@
 #include <SDL3/SDL.h>
 #include <core/StatusCodeOk.hpp>
 #include <core/StatusCodeWindowApiLoadingFailed.hpp>
+#include <core/StatusCodeWindowCreationFailed.hpp>
 #include <ls-std/core/evaluator/NullPointerArgumentEvaluator.hpp>
 #include <window/SdlApi.hpp>
 #include <window/SdlWindowApi.hpp>
 
 using ls::atlantis::core::StatusCodeOk;
 using ls::atlantis::core::StatusCodeWindowApiLoadingFailed;
+using ls::atlantis::core::StatusCodeWindowCreationFailed;
 using ls::atlantis::interfaces::AStatusCode;
 using ls::atlantis::interfaces::ISdlApi;
 using ls::std::core::NullPointerArgumentEvaluator;
@@ -23,7 +25,9 @@ using ::std::shared_ptr;
 SdlWindowApi::SdlWindowApi() : SdlWindowApi(make_shared<SdlApi>())
 {}
 
-SdlWindowApi::SdlWindowApi(const shared_ptr<ISdlApi> &_sdlApi) : sdlApi(_sdlApi)
+SdlWindowApi::SdlWindowApi(const shared_ptr<ISdlApi> &_sdlApi)
+  : sdlApi(_sdlApi),
+    window(nullptr, [this](SDL_Window *_window) { this->sdlApi->DestroyWindow(_window); })
 {
   NullPointerArgumentEvaluator(_sdlApi).evaluate();
 }
@@ -35,15 +39,29 @@ SdlWindowApi::~SdlWindowApi()
 
 shared_ptr<AStatusCode> SdlWindowApi::init()
 {
-  return SdlWindowApi::_initApi();
+  shared_ptr<AStatusCode> statusCode = this->_initApi();
+
+  if (statusCode->getId() == StatusCodeOk{}.getId())
+  {
+    statusCode = this->_createWindow();
+  }
+
+  return statusCode;
 }
 
 shared_ptr<AStatusCode> SdlWindowApi::_createWindow()
 {
+  window.reset(sdlApi->CreateWindow("", 0, 0, SDL_WINDOW_FULLSCREEN));
+
+  if (window == nullptr)
+  {
+    return make_shared<StatusCodeWindowCreationFailed>();
+  }
+
   return make_shared<StatusCodeOk>();
 }
 
-shared_ptr<AStatusCode> SdlWindowApi::_initApi()
+shared_ptr<AStatusCode> SdlWindowApi::_initApi() const
 {
   shared_ptr<AStatusCode> statusCode = make_shared<StatusCodeOk>();
 

+ 34 - 0
test/core/StatusCodeWindowCreationFailedTest.cpp

@@ -0,0 +1,34 @@
+/*
+ * author: Patrick-Christopher Mattulat
+ * e-mail: webmaster@lynarstudios.com
+ */
+
+#include <core/StatusCodeWindowCreationFailed.hpp>
+#include <core/StatusCodes.hpp>
+#include <gtest/gtest.h>
+
+using ls::atlantis::core::StatusCodeWindowCreationFailed;
+using ls::atlantis::core::StatusCodes;
+using ::std::string;
+using ::testing::Test;
+
+namespace
+{
+  class StatusCodeWindowCreationFailedTest : public Test
+  {
+    public:
+
+      StatusCodeWindowCreationFailedTest() = default;
+      ~StatusCodeWindowCreationFailedTest() override = default;
+  };
+
+  TEST_F(StatusCodeWindowCreationFailedTest, getId)
+  {
+    ASSERT_EQ(StatusCodes::WINDOW_CREATION_FAILED, StatusCodeWindowCreationFailed().getId());
+  }
+
+  TEST_F(StatusCodeWindowCreationFailedTest, getText)
+  {
+    ASSERT_EQ(string("window creation failed"), StatusCodeWindowCreationFailed().getText());
+  }
+}

+ 15 - 0
test/window/SdlWindowApiTest.cpp

@@ -18,6 +18,7 @@ using ls::std::core::IllegalArgumentException;
 using ::std::make_shared;
 using ::std::shared_ptr;
 using ::testing::Return;
+using ::testing::StrEq;
 using ::testing::Test;
 
 namespace
@@ -39,7 +40,12 @@ namespace
 
   TEST_F(SdlWindowApiTest, init)
   {
+    int dummyWindowHandle = 0;
+    auto *fakeWindow = static_cast<SDL_Window *>(static_cast<void *>(&dummyWindowHandle));
+
     EXPECT_CALL(*sdlApiMock, Init(SDL_INIT_VIDEO)).WillOnce(Return(1));
+    EXPECT_CALL(*sdlApiMock, CreateWindow(StrEq(""), 0, 0, SDL_WINDOW_FULLSCREEN)).WillOnce(Return(fakeWindow));
+    EXPECT_CALL(*sdlApiMock, DestroyWindow(fakeWindow));
     EXPECT_CALL(*sdlApiMock, Quit());
 
     ASSERT_EQ(StatusCodes::OK, SdlWindowApi(sdlApiMock).init()->getId());
@@ -52,4 +58,13 @@ namespace
 
     ASSERT_EQ(StatusCodes::WINDOW_API_LOADING_FAILED, SdlWindowApi(sdlApiMock).init()->getId());
   }
+
+  TEST_F(SdlWindowApiTest, init_windowCreationFailed)
+  {
+    EXPECT_CALL(*sdlApiMock, Init(SDL_INIT_VIDEO)).WillOnce(Return(1));
+    EXPECT_CALL(*sdlApiMock, CreateWindow(StrEq(""), 0, 0, SDL_WINDOW_FULLSCREEN)).WillOnce(Return(nullptr));
+    EXPECT_CALL(*sdlApiMock, Quit());
+
+    ASSERT_EQ(StatusCodes::WINDOW_CREATION_FAILED, SdlWindowApi(sdlApiMock).init()->getId());
+  }
 }

+ 2 - 0
test/window/mock/SdlApiMock.hpp

@@ -18,6 +18,8 @@ namespace ls::atlantis::window::test
       SdlApiMock();
       ~SdlApiMock() override;
 
+      MOCK_METHOD(SDL_Window *, CreateWindow, (const char *, int, int, SDL_WindowFlags), (override));
+      MOCK_METHOD(void, DestroyWindow, (SDL_Window *), (override));
       MOCK_METHOD(bool, Init, (SDL_InitFlags flags), (override));
       MOCK_METHOD(void, Quit, (), (override));
   };