Просмотр исходного кода

Add basic window creation functionality

Patrick-Christopher Mattulat 1 неделя назад
Родитель
Сommit
df8f7c3d91

+ 2 - 0
CMakeLists.txt

@@ -48,6 +48,7 @@ endif ()
 set(ATLANTIS_CORE_SOURCES
 set(ATLANTIS_CORE_SOURCES
         ${CMAKE_CURRENT_SOURCE_DIR}/source/core/StatusCodeOk.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/core/StatusCodeOk.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/core/StatusCodeWindowApiLoadingFailed.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
 set(ATLANTIS_CORE_TEST_SOURCES
         ${CMAKE_CURRENT_SOURCE_DIR}/test/core/StatusCodeOkTest.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/core/StatusCodeOkTest.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/core/StatusCodeWindowApiLoadingFailedTest.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.
 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.
 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.
 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.
 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).
 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]]__.
 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
   enum StatusCodes
   {
   {
     OK = 1,
     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();
       ISdlApi();
       virtual ~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 bool Init(SDL_InitFlags flags) = 0;
       virtual void Quit() = 0;
       virtual void Quit() = 0;
   };
   };

+ 2 - 0
include/window/SdlApi.hpp

@@ -18,6 +18,8 @@ namespace ls::atlantis::window
       SdlApi();
       SdlApi();
       ~SdlApi() override;
       ~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;
       bool Init(SDL_InitFlags flags) override;
       void Quit() override;
       void Quit() override;
   };
   };

+ 4 - 2
include/window/SdlWindowApi.hpp

@@ -10,6 +10,7 @@
 #include <interface/AStatusCode.hpp>
 #include <interface/AStatusCode.hpp>
 #include <interface/ISdlApi.hpp>
 #include <interface/ISdlApi.hpp>
 #include <interface/IWindowApi.hpp>
 #include <interface/IWindowApi.hpp>
+#include <functional>
 #include <memory>
 #include <memory>
 
 
 namespace ls::atlantis::window
 namespace ls::atlantis::window
@@ -26,10 +27,11 @@ namespace ls::atlantis::window
 
 
     private:
     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::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;
 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)
 bool SdlApi::Init(const SDL_InitFlags flags)
 {
 {
   return SDL_Init(flags);
   return SDL_Init(flags);

+ 21 - 3
source/window/SdlWindowApi.cpp

@@ -6,12 +6,14 @@
 #include <SDL3/SDL.h>
 #include <SDL3/SDL.h>
 #include <core/StatusCodeOk.hpp>
 #include <core/StatusCodeOk.hpp>
 #include <core/StatusCodeWindowApiLoadingFailed.hpp>
 #include <core/StatusCodeWindowApiLoadingFailed.hpp>
+#include <core/StatusCodeWindowCreationFailed.hpp>
 #include <ls-std/core/evaluator/NullPointerArgumentEvaluator.hpp>
 #include <ls-std/core/evaluator/NullPointerArgumentEvaluator.hpp>
 #include <window/SdlApi.hpp>
 #include <window/SdlApi.hpp>
 #include <window/SdlWindowApi.hpp>
 #include <window/SdlWindowApi.hpp>
 
 
 using ls::atlantis::core::StatusCodeOk;
 using ls::atlantis::core::StatusCodeOk;
 using ls::atlantis::core::StatusCodeWindowApiLoadingFailed;
 using ls::atlantis::core::StatusCodeWindowApiLoadingFailed;
+using ls::atlantis::core::StatusCodeWindowCreationFailed;
 using ls::atlantis::interfaces::AStatusCode;
 using ls::atlantis::interfaces::AStatusCode;
 using ls::atlantis::interfaces::ISdlApi;
 using ls::atlantis::interfaces::ISdlApi;
 using ls::std::core::NullPointerArgumentEvaluator;
 using ls::std::core::NullPointerArgumentEvaluator;
@@ -23,7 +25,9 @@ using ::std::shared_ptr;
 SdlWindowApi::SdlWindowApi() : SdlWindowApi(make_shared<SdlApi>())
 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();
   NullPointerArgumentEvaluator(_sdlApi).evaluate();
 }
 }
@@ -35,15 +39,29 @@ SdlWindowApi::~SdlWindowApi()
 
 
 shared_ptr<AStatusCode> SdlWindowApi::init()
 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()
 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>();
   return make_shared<StatusCodeOk>();
 }
 }
 
 
-shared_ptr<AStatusCode> SdlWindowApi::_initApi()
+shared_ptr<AStatusCode> SdlWindowApi::_initApi() const
 {
 {
   shared_ptr<AStatusCode> statusCode = make_shared<StatusCodeOk>();
   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::make_shared;
 using ::std::shared_ptr;
 using ::std::shared_ptr;
 using ::testing::Return;
 using ::testing::Return;
+using ::testing::StrEq;
 using ::testing::Test;
 using ::testing::Test;
 
 
 namespace
 namespace
@@ -39,7 +40,12 @@ namespace
 
 
   TEST_F(SdlWindowApiTest, init)
   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, 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());
     EXPECT_CALL(*sdlApiMock, Quit());
 
 
     ASSERT_EQ(StatusCodes::OK, SdlWindowApi(sdlApiMock).init()->getId());
     ASSERT_EQ(StatusCodes::OK, SdlWindowApi(sdlApiMock).init()->getId());
@@ -52,4 +58,13 @@ namespace
 
 
     ASSERT_EQ(StatusCodes::WINDOW_API_LOADING_FAILED, SdlWindowApi(sdlApiMock).init()->getId());
     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();
       ~SdlApiMock() override;
       ~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(bool, Init, (SDL_InitFlags flags), (override));
       MOCK_METHOD(void, Quit, (), (override));
       MOCK_METHOD(void, Quit, (), (override));
   };
   };