diff --git a/crogine/include/crogine/ecs/systems/ModelRenderer.hpp b/crogine/include/crogine/ecs/systems/ModelRenderer.hpp index ebfdd2161..6360878ce 100644 --- a/crogine/include/crogine/ecs/systems/ModelRenderer.hpp +++ b/crogine/include/crogine/ecs/systems/ModelRenderer.hpp @@ -83,6 +83,17 @@ namespace cro */ void render(Entity, const RenderTarget&) override; + /*! + \brief Returns the size of the draw list of the given camera for the given pass + Camera indices can be retrieved with Camera::getDrawlistIndex(). For example + \begincode + std::size_t visible = scene.getSystem()->getVisibleCount(camera.getDrawlistIndex(), cro::Camera::Pass::Final); + \endcode + \param cameraIndex The index of the camera's drawlist + \param passIndex the ID of the pass to query + */ + std::size_t getVisibleCount(std::size_t cameraIndex, std::int32_t passIndex) const; + void onEntityAdded(Entity) override; void onEntityRemoved(Entity) override; diff --git a/crogine/src/core/FileSystem.cpp b/crogine/src/core/FileSystem.cpp index a5cfacb73..48f1b4560 100644 --- a/crogine/src/core/FileSystem.cpp +++ b/crogine/src/core/FileSystem.cpp @@ -46,6 +46,7 @@ source distribution. #ifdef _WIN32 #include #include +#include //technically crossplatform but unsupported on the oldest version of macOS which cro supports #define PATH_SEPARATOR_CHAR '\\' #define PATH_SEPARATOR_STRING "\\" #ifdef _MSC_VER @@ -244,24 +245,65 @@ bool FileSystem::createDirectory(const std::string& path) { //TODO regex this or at least check for illegal chars #ifdef _WIN32 - if (_mkdir(path.c_str()) == 0) + std::error_code ec; + if (!std::filesystem::create_directories(/*std::filesystem::u8path*/(path), ec)) { - LOG("Created directory " + path, cro::Logger::Type::Info); - return true; - } - else - { - auto result = errno; - if (result == EEXIST) + //this might be 0 if the directory already exists + if (ec.value() != 0) { - Logger::log(path + " directory already exists!", Logger::Type::Info); - } - else if (result == ENOENT) - { - Logger::log("Unable to create " + path + " directory not found.", Logger::Type::Error); + std::stringstream ss; + ss << ec.message() << " - Error Code: " << ec.value(); + + //TODO these are WinAPI error codes - haven't tested + //MinGW etc to see if these are what they report. + switch (ec.value()) + { + default: ss << " (unknown error)"; break; + case 1: ss << " (invalid function)"; break; + case 2: ss << " (file not found)"; break; + case 3: ss << " (path not found)"; break; + case 5: ss << " (access denied)"; break; + case 8: ss << " (not enough memory)"; break; + case 18: ss << " (no more files)"; break; + case 32: ss << " (sharing violation)"; break; + case 50: ss << " (not supproted)"; break; + case 53: ss << " (bad netpath)"; break; + case 80: ss << " (file exists)"; break; + case 87: ss << " (invalid parameter)"; break; + case 122: ss << " (insufficient buffer)"; break; + case 123: ss << " (invalid name)"; break; + case 145: ss << " (directory not empty)"; break; + case 183: ss << " (already exists)"; break; + case 206: ss << " (filename exceeds range)"; break; + case 267: ss << " (invalid directory name)"; break; + case 4393: ss << " (reparse tag invalid)"; break; + } + + Logger::log(ss.str(), Logger::Type::Error, Logger::Output::All); + return false; } } - return false; + return true; + + + //if (_mkdir(path.c_str()) == 0) + //{ + // LOG("Created directory " + path, cro::Logger::Type::Info); + // return true; + //} + //else + //{ + // auto result = errno; + // if (result == EEXIST) + // { + // Logger::log(path + " directory already exists!", Logger::Type::Info); + // } + // else if (result == ENOENT) + // { + // Logger::log("Unable to create " + path + ": parent directory not found.", Logger::Type::Error, Logger::Output::All); + // } + //} + //return false; #else if (mkdir(path.c_str(), 0777) == 0) { @@ -280,7 +322,7 @@ bool FileSystem::createDirectory(const std::string& path) break; case ENOENT: { - Logger::log("Unable to create " + path + " directory not found.", Logger::Type::Error); + Logger::log("Unable to create " + path + ": parent directory not found.", Logger::Type::Error, Logger::Output::All); } break; case EFAULT: diff --git a/crogine/src/ecs/systems/ModelRenderer.cpp b/crogine/src/ecs/systems/ModelRenderer.cpp index 945595fbf..00df65adf 100644 --- a/crogine/src/ecs/systems/ModelRenderer.cpp +++ b/crogine/src/ecs/systems/ModelRenderer.cpp @@ -246,6 +246,21 @@ void ModelRenderer::render(Entity camera, const RenderTarget& rt) } } +std::size_t ModelRenderer::getVisibleCount(std::size_t cameraIndex, std::int32_t passIndex) const +{ + CRO_ASSERT(m_drawLists.size() < cameraIndex, ""); + switch (passIndex) + { + default: return 0; + case Camera::Pass::Final: + case Camera::Pass::Refraction: + return m_drawLists[cameraIndex][Camera::Pass::Final].size(); + case Camera::Pass::Reflection: + return m_drawLists[cameraIndex][Camera::Pass::Reflection].size(); + } + return 0; +} + void ModelRenderer::onEntityAdded(Entity entity) { auto& model = entity.getComponent(); diff --git a/crogine/src/ecs/systems/RenderSystem2D.cpp b/crogine/src/ecs/systems/RenderSystem2D.cpp index 8011c7e23..32a400a03 100644 --- a/crogine/src/ecs/systems/RenderSystem2D.cpp +++ b/crogine/src/ecs/systems/RenderSystem2D.cpp @@ -96,7 +96,7 @@ void RenderSystem2D::updateDrawList(Entity camEnt) //m_dirtyEnts.clear(); auto& camera = camEnt.getComponent(); - CRO_ASSERT(camera.isOrthographic(), ""); + CRO_ASSERT(camera.isOrthographic(), "Camera is not orthographic"); if (m_drawLists.size() <= camera.getDrawListIndex()) { diff --git a/libsocial/include/Social.hpp b/libsocial/include/Social.hpp index c1e3e99ce..6a6627005 100644 --- a/libsocial/include/Social.hpp +++ b/libsocial/include/Social.hpp @@ -45,7 +45,7 @@ source distribution. //(terrain vertex data and materials changed 1100 -> 1110) //(player avatar data format changed 1110 -> 1120) static constexpr std::uint16_t CURRENT_VER = 1120; -static const std::string StringVer("1.12.2"); +static const std::string StringVer("1.12.3"); class Social final @@ -97,6 +97,9 @@ class Social final }; static cro::Image userIcon; + static bool isGreyscale() { return false; } + static bool isValid() { return true; } + static bool isValid(const std::string&) { return true; } static bool isAvailable() { return false; } static bool isSteamdeck() { return false; } static cro::Image getUserIcon(std::uint64_t) { return userIcon; } diff --git a/samples/golf/CMakeLists.txt b/samples/golf/CMakeLists.txt index 568abb38c..f5663e273 100644 --- a/samples/golf/CMakeLists.txt +++ b/samples/golf/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.2.2) #Xcode 10 will default to Mojave (must be done BEFORE project()) if (APPLE) - SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.14" CACHE STRING "Minimum OS X deployment version") + SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version") SET(MACOS_BUNDLE False CACHE BOOL "") if(MACOS_BUNDLE) diff --git a/samples/golf/src/golf/FogShader.inl b/samples/golf/src/golf/FogShader.inl index f5736a4fc..a98293987 100644 --- a/samples/golf/src/golf/FogShader.inl +++ b/samples/golf/src/golf/FogShader.inl @@ -59,6 +59,10 @@ const float ZNear = 0.1; #endif const float ZFar = ZFAR; +#if !defined(DESAT) +#define DESAT 0.06 +#endif + uniform sampler2D u_texture; uniform sampler2D u_depthTexture; @@ -91,7 +95,7 @@ void main() vec4 colour = TEXTURE(u_texture, v_texCoord) * v_colour; vec3 desat = vec3(dot(colour.rgb, vec3(0.299, 0.587, 0.114))); vec3 dimmed = colour.rgb * (1.0 - (0.3 * desatAmount)); - colour.rgb = mix(dimmed, desat, desatAmount * 0.06); + colour.rgb = mix(dimmed, desat, desatAmount * DESAT); float depthSample = TEXTURE(u_depthTexture, v_texCoord).r; diff --git a/samples/golf/src/golf/GolfState.cpp b/samples/golf/src/golf/GolfState.cpp index c9167b534..22e44de49 100644 --- a/samples/golf/src/golf/GolfState.cpp +++ b/samples/golf/src/golf/GolfState.cpp @@ -238,7 +238,7 @@ GolfState::GolfState(cro::StateStack& stack, cro::State::Context context, Shared } }); - registerCommand("fog", [&](const std::string& param) + /*registerCommand("fog", [&](const std::string& param) { if (param.empty()) { @@ -256,7 +256,7 @@ GolfState::GolfState(cro::StateStack& stack, cro::State::Context context, Shared glUseProgram(shader.getGLHandle()); glUniform1f(uniform, std::clamp(f, 0.f, 1.f)); } - }); + });*/ shadowQuality.update(sd.hqShadows); @@ -1946,7 +1946,12 @@ void GolfState::loadAssets() m_postProcesses[PostID::Noise].shader = shader; //fog - m_resources.shaders.loadFromString(ShaderID::Fog, FogVert, FogFrag, "#define ZFAR 320.0\n"); + std::string desat; + if (Social::isGreyscale()) + { + desat = "#define DESAT 1.0\n"; + } + m_resources.shaders.loadFromString(ShaderID::Fog, FogVert, FogFrag, "#define ZFAR 320.0\n" + desat); shader = &m_resources.shaders.get(ShaderID::Fog); m_postProcesses[PostID::Fog].shader = shader; //depth uniform is set after creating the UI once we know the render texture is created @@ -2790,7 +2795,7 @@ void GolfState::loadAssets() } } - if (!path.empty() + if (!path.empty() && Social::isValid(path) && cro::FileSystem::fileExists(cro::FileSystem::getResourcePath() + path)) { if (modelDef.loadFromFile(path)) @@ -3252,10 +3257,6 @@ void GolfState::loadAssets() m_windBuffer.addShader(*shader); createClouds(); - if (cro::SysTime::now().months() == 6) - { - buildBow(); - } //reserve the slots for each hole score for (auto& client : m_sharedData.connectionData) @@ -4295,13 +4296,21 @@ void GolfState::buildScene() sunEnt.getComponent().setRotation(cro::Transform::Y_AXIS, -130.f * cro::Util::Const::degToRad); sunEnt.getComponent().rotate(cro::Transform::X_AXIS, -75.f * cro::Util::Const::degToRad); - if (cro::SysTime::now().months() == 12) + if (auto month = cro::SysTime::now().months(); month == 12) { if (cro::Util::Random::value(0, 20) == 0) { createWeather(WeatherType::Snow); } } + else if (month == 6) + { + if (cro::Util::Random::value(0, 5) == 0) + { + buildBow(); + } + } + //else //{ // createWeather(WeatherType::Rain); diff --git a/samples/golf/src/golf/MenuCreation.cpp b/samples/golf/src/golf/MenuCreation.cpp index e97f20651..ce8e61c4d 100644 --- a/samples/golf/src/golf/MenuCreation.cpp +++ b/samples/golf/src/golf/MenuCreation.cpp @@ -664,8 +664,9 @@ void MenuState::createMainMenu(cro::Entity parent, std::uint32_t mouseEnter, std return entity; }; - - if (!m_courseData.empty() + auto validData = Social::isValid(); + if (validData + &&!m_courseData.empty() && !m_sharedData.ballInfo.empty() && ! m_sharedData.avatarInfo.empty()) { @@ -719,6 +720,10 @@ void MenuState::createMainMenu(cro::Entity parent, std::uint32_t mouseEnter, std else { std::string str = "Error:\n"; + if (!validData) + { + str += "Invalid Course Data\n"; + } if (m_courseData.empty()) { str += "No course data found\n"; @@ -3064,7 +3069,7 @@ void MenuState::updateCourseRuleString() { if (!data->isUser) { - std::stringstream ss; + /*std::stringstream ss; float playTime = Achievements::getAvgStat(m_sharedData.mapDirectory); if (playTime > 0) { @@ -3079,7 +3084,9 @@ void MenuState::updateCourseRuleString() ss << "Top Players: "; cro::String scoreStr(ss.str()); - scoreStr += Social::getTopFive(m_sharedData.mapDirectory, m_sharedData.holeCount); + scoreStr += Social::getTopFive(m_sharedData.mapDirectory, m_sharedData.holeCount);*/ + + auto scoreStr = Social::getTopFive(m_sharedData.mapDirectory, m_sharedData.holeCount); m_lobbyWindowEntities[LobbyEntityID::CourseTicker].getComponent().setString(scoreStr); m_lobbyWindowEntities[LobbyEntityID::CourseTicker].getComponent().setScale(glm::vec2(1.f)); m_lobbyWindowEntities[LobbyEntityID::CourseTicker].getComponent().setPosition(glm::vec2(200.f,0.f)); diff --git a/samples/golf/src/golf/MenuState.cpp b/samples/golf/src/golf/MenuState.cpp index 04fab2dc8..9d2729d6e 100644 --- a/samples/golf/src/golf/MenuState.cpp +++ b/samples/golf/src/golf/MenuState.cpp @@ -359,12 +359,12 @@ MenuState::MenuState(cro::StateStack& stack, cro::State::Context context, Shared // { // if (ImGui::Begin("buns")) // { - // /*auto size = glm::vec2(LabelTextureSize); + // auto size = glm::vec2(LabelTextureSize); // for (const auto& t : m_sharedData.nameTextures) // { // ImGui::Image(t.getTexture(), { size.x, size.y }, { 0.f, 1.f }, { 1.f, 0.f }); // ImGui::SameLine(); - // }*/ + // } // } // ImGui::End(); // }); @@ -801,7 +801,7 @@ void MenuState::handleMessage(const cro::Message& msg) { const auto& data = msg.getData(); if (data.type == Social::SocialEvent::AvatarDownloaded - && m_currentMenu == MenuID::Lobby) + && (m_currentMenu == MenuID::Lobby || m_currentMenu == MenuID::Join)) { //TODO we've only updated a specific avatar //so it would be preferable to not update ALL diff --git a/samples/golf/src/golf/PlayerColours.hpp b/samples/golf/src/golf/PlayerColours.hpp index 1cf7b7548..553db35bc 100644 --- a/samples/golf/src/golf/PlayerColours.hpp +++ b/samples/golf/src/golf/PlayerColours.hpp @@ -111,7 +111,7 @@ namespace pc static inline const std::array PairCounts = { Palette.size(), - 8, + 16, Palette.size(), Palette.size(), Palette.size(), diff --git a/samples/golf/src/golf/ProfileState.cpp b/samples/golf/src/golf/ProfileState.cpp index d3433fd6f..49ffa95bb 100644 --- a/samples/golf/src/golf/ProfileState.cpp +++ b/samples/golf/src/golf/ProfileState.cpp @@ -245,7 +245,8 @@ bool ProfileState::handleEvent(const cro::Event& evt) { auto currentMenu = m_uiScene.getSystem()->getActiveGroup(); - if (currentMenu != MenuID::Main) + if (currentMenu != MenuID::Main + && currentMenu != MenuID::Dummy) { auto flyoutID = currentMenu - MenuID::Hair; auto bounds = m_flyouts[flyoutID].background.getComponent().getLocalBounds(); diff --git a/samples/golf/src/golf/Weather.cpp b/samples/golf/src/golf/Weather.cpp index 8ce46602a..22f62fded 100644 --- a/samples/golf/src/golf/Weather.cpp +++ b/samples/golf/src/golf/Weather.cpp @@ -340,6 +340,18 @@ void GolfState::createClouds() void GolfState::buildBow() { + if (Social::isGreyscale()) + { + createWeather(WeatherType::Rain); + + auto& shader = m_resources.shaders.get(ShaderID::Fog); + auto uniform = shader.getUniformID("u_density"); + glUseProgram(shader.getGLHandle()); + glUniform1f(uniform, 0.89f); + + return; + } + auto meshID = m_resources.meshes.loadMesh(cro::DynamicMeshBuilder(cro::VertexProperty::Position | cro::VertexProperty::Colour | cro::VertexProperty::UV0, 1, GL_TRIANGLE_STRIP)); auto* meshData = &m_resources.meshes.getMesh(meshID);