Skip to content

Commit

Permalink
- Released version 1.0
Browse files Browse the repository at this point in the history
- Modified README
  • Loading branch information
kkEngine committed Jul 28, 2024
1 parent d1846c7 commit 7ea5df3
Show file tree
Hide file tree
Showing 12 changed files with 140 additions and 55 deletions.
8 changes: 4 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ cmake_minimum_required(VERSION 3.23)
option(BUILD_AS_SHARED "Build as dll skse plugin else build as static lib" ON)

# Version
set(LIB_MAJOR_VERSION 0)
set(LIB_MINOR_VERSION 1)
set(API_MAJOR_VERSION 0)
set(API_MINOR_VERSION 1)
set(LIB_MAJOR_VERSION 1)
set(LIB_MINOR_VERSION 0)
set(API_MAJOR_VERSION 1)
set(API_MINOR_VERSION 0)

# VCPKG config
string(REPLACE "\\" "/" ENV_VCPKG_ROOT "$ENV{VCPKG_ROOT}")
Expand Down
95 changes: 90 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,86 @@

UI platform for Skyrim with CEF (Chromium Embedded Framework) integration and more. You can create interface based on html5, css, javascript. This project is a part of NirnLab project.

## NirnLab
## Features
- Chromium browser is rendered in Skyrim's native menu (can take screenshots, using native cursor)
- Creating multiple browsers
- Changing keyboard layout out of the box (SHIFT-CTRL or SHIFT-ALT) including console
- Binding js to cpp function callbacks
- Auto closing CEF processes in case of the game crash

NirnLab is a competitive MMO-like mod for Skyrim which will be announced after the main part is completed.
If you want to follow the progress and news, subscribe to [![Discord](https://img.shields.io/discord/1004071212361711678?label=Discord&logo=Discord)](https://discord.gg/3YDR4pDJYy).
## Usage as skse plugin (preferred)
You can find all public APIs in this [folder](https://github.com/kkEngine/NirnLabUIPlatform/tree/main/src/UIPlatform/NirnLabUIPlatformAPI). Copy and include the folder in your project (included in release).
Test [examples](https://github.com/kkEngine/NirnLabUIPlatform/tree/main/src/UIPlatformTest)

# Get API (CommonLibSSE example)
First of all we need to check the API version. If major versions are defferent i don't recommend continuing (may crash).

Send request version message when all plugin loaded (kPostPostLoad)
```cpp
SKSE::GetMessagingInterface()->Dispatch(NL::UI::APIMessageType::RequestVersion, nullptr, 0, LibVersion::PROJECT_NAME);
```
Response message will contain API and Lib versions
```cpp
SKSE::GetMessagingInterface()->RegisterListener(LibVersion::PROJECT_NAME, [](SKSE::MessagingInterface::Message* a_msg) {
switch (a_msg->type)
{
case NL::UI::APIMessageType::ResponseVersion:
// API and Lib versions
const auto versionInfo = reinterpret_cast<NL::UI::ResponseVersionMessage*>(a_msg->data);
break;
}
});
```

Check the API version and if it's ok, request API
```cpp
SKSE::GetMessagingInterface()->Dispatch(NL::UI::APIMessageType::RequestAPI, nullptr, 0, NL::UI::LibVersion::PROJECT_NAME);
```
When a first plugin requests API, library and CEF will initialize
Response message will contain API struct. You can save the API pointer and use it in the future.
```cpp
SKSE::GetMessagingInterface()->RegisterListener(LibVersion::PROJECT_NAME, [](SKSE::MessagingInterface::Message* a_msg) {
switch (a_msg->type)
{
case NL::UI::APIMessageType::ResponseAPI:
auto api = reinterpret_cast<NL::UI::ResponseAPIMessage*>(a_msg->data)->API;
break;
}
});
```

# Create browser
```cpp
NL::CEF::IBrowser* g_browser = nullptr;
NL::UI::IUIPlatformAPI::BrowserRefHandle g_browserHandle = NL::UI::IUIPlatformAPI::InvalidBrowserRefHandle;

void CreateBrowser(NL::UI::IUIPlatformAPI* a_api)
{
g_browserHandle = a_api->AddOrGetBrowser("MyPluginCEF", nullptr, 0, "https://www.youtube.com", g_browser);
if (g_browserHandle == NL::UI::IUIPlatformAPI::InvalidBrowserRefHandle)
{
spdlog::error("browser handle is invalid");
return;
}

## Examples
todo
// Keep "g_browserHandle" util you need a browser
// When the browser is no longer needed, release it using a_api->ReleaseBrowserHandle();
// If this was the last browser handle, the browser will be deleted

// Check NL::CEF::IBrowser interface for more features
m_browser->ToggleBrowserFocusByKeys(RE::BSKeyboardDevice::Keys::kF6, 0);
g_browser->ToggleBrowserVisibleByKeys(RE::BSKeyboardDevice::Keys::kF7, 0);
g_browser->SetBrowserFocused(true);
g_browser->ExecuteJavaScript("window.myString = 'Hello CEF'");
}

void ReleaseBrowser(NL::UI::IUIPlatformAPI::BrowserRefHandle a_handle)
{
g_browser = nullptr;
a_api->ReleaseBrowserHandle(g_browserHandle);
g_browserHandle = NL::UI::IUIPlatformAPI::InvalidBrowserRefHandle;
}
```
## Dev and build requirements
- CMake 3.23+
Expand All @@ -21,5 +94,17 @@ todo
- Address library (https://www.nexusmods.com/skyrimspecialedition/mods/32444)
- SKSE (https://skse.silverlock.org/)
## NirnLab
NirnLab is a competitive MMO-like mod for Skyrim which will be announced after the main part is completed.
If you want to follow the progress and news, subscribe to [![Discord](https://img.shields.io/discord/1004071212361711678?label=Discord&logo=Discord)](https://discord.gg/3YDR4pDJYy).
### Thanks to
[@Pospelove](https://github.com/Pospelove)
[Skymp](https://github.com/skyrim-multiplayer/skymp)
[CommonLibSSE](https://github.com/Ryan-rsm-McKenzie/CommonLibSSE)
[CommonLibSSE-NG](https://github.com/CharmedBaryon/CommonLibSSE-NG)
Chromium Embedded Framework ([CEF](https://bitbucket.org/chromiumembedded/cef))
### License
MIT
2 changes: 1 addition & 1 deletion src/UIPlatform/Controllers/PublicAPIController.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace NL::Controllers
};

protected:
NL::UI::ResponseVersionMessage m_rvMessage{LibVersion::AS_INT, APIVersion::AS_INT};
NL::UI::ResponseVersionMessage m_rvMessage{NL::UI::LibVersion::AS_INT, NL::UI::APIVersion::AS_INT};
NL::UI::ResponseAPIMessage m_rAPIMessage{this};

std::atomic<BrowserRefHandle> m_currentRefHandle{1};
Expand Down
6 changes: 3 additions & 3 deletions src/UIPlatform/NirnLabUIPlatformAPI/API.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ namespace NL::UI

/// <summary>
/// Response with version info. See ResponseVersionMessage struct.
/// You should check current API version (APIVersion::AS_INT) and version in response.
/// You should check current API version (NL::UI::APIVersion::AS_INT) and version in response.
/// It is not guaranteed that the major versions are compatible. In this case, I recommend not using the library.
/// </summary>
ResponseVersion,
Expand All @@ -69,12 +69,12 @@ namespace NL::UI
/// <summary>
/// NirnLabUIPlatform version
/// </summary>
std::uint32_t libVersion = LibVersion::AS_INT;
std::uint32_t libVersion = NL::UI::LibVersion::AS_INT;

/// <summary>
/// NirnLabUIPlatform API version
/// </summary>
std::uint32_t apiVersion = APIVersion::AS_INT;
std::uint32_t apiVersion = NL::UI::APIVersion::AS_INT;
};

struct ResponseAPIMessage
Expand Down
16 changes: 8 additions & 8 deletions src/UIPlatform/NirnLabUIPlatformAPI/Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

#include <cstdint>

namespace LibVersion
namespace NL::UI::LibVersion
{
inline constexpr std::uint32_t MAJOR = 0;
inline constexpr std::uint32_t MINOR = 1;
inline constexpr std::uint32_t MAJOR = 1;
inline constexpr std::uint32_t MINOR = 0;
inline constexpr auto PROJECT_NAME = "NirnLabUIPlatform";

inline constexpr auto MAJOR_MULT = 100000;
inline constexpr auto AS_STRING = "0.1";
inline constexpr auto AS_STRING = "1.0";
inline constexpr std::uint32_t AS_INT = (static_cast<std::uint32_t>(MAJOR * MAJOR_MULT + MINOR));

inline std::uint32_t GetMajorVersion(std::uint32_t a_version)
Expand All @@ -23,13 +23,13 @@ namespace LibVersion
}
}

namespace APIVersion
namespace NL::UI::APIVersion
{
inline constexpr std::uint32_t MAJOR = 0;
inline constexpr std::uint32_t MINOR = 1;
inline constexpr std::uint32_t MAJOR = 1;
inline constexpr std::uint32_t MINOR = 0;

inline constexpr auto MAJOR_MULT = 100000;
inline constexpr auto AS_STRING = "0.1";
inline constexpr auto AS_STRING = "1.0";
inline constexpr std::uint32_t AS_INT = (static_cast<std::uint32_t>(MAJOR * MAJOR_MULT + MINOR));

inline std::uint32_t GetMajorVersion(std::uint32_t a_version)
Expand Down
4 changes: 2 additions & 2 deletions src/UIPlatform/Utils/PathUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace NL::Utils
{
static inline std::filesystem::path GetTempAppDataPath()
{
auto appPath = std::filesystem::temp_directory_path() / LibVersion::PROJECT_NAME;
auto appPath = std::filesystem::temp_directory_path() / NL::UI::LibVersion::PROJECT_NAME;
CreateDirectoryW(appPath.wstring().c_str(), 0);
return appPath;
}
Expand All @@ -21,7 +21,7 @@ namespace NL::Utils

if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &pwStr)))
{
fsPath = std::filesystem::path(pwStr) / LibVersion::PROJECT_NAME;
fsPath = std::filesystem::path(pwStr) / NL::UI::LibVersion::PROJECT_NAME;
}
CoTaskMemFree(pwStr);
return fsPath;
Expand Down
6 changes: 3 additions & 3 deletions src/UIPlatform/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ void InitDefaultLog()
SKSE::stl::report_and_fail("Failed to find standard logging directory"sv);
}

*path /= fmt::format("{}.log"sv, LibVersion::PROJECT_NAME);
*path /= fmt::format("{}.log"sv, NL::UI::LibVersion::PROJECT_NAME);
auto sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(path->string(), true);
#endif

Expand Down Expand Up @@ -58,8 +58,8 @@ void InitCefSubprocessLog()

extern "C" DLLEXPORT constinit auto SKSEPlugin_Version = []() {
SKSE::PluginVersionData v{};
v.pluginVersion = LibVersion::AS_INT;
v.PluginName(LibVersion::PROJECT_NAME);
v.pluginVersion = NL::UI::LibVersion::AS_INT;
v.PluginName(NL::UI::LibVersion::PROJECT_NAME);
v.AuthorName("kkEngine"sv);
v.CompatibleVersions({SKSE::RUNTIME_SSE_1_6_640, REL::Version(1, 6, 1170, 0)});
v.UsesAddressLibrary(true);
Expand Down
6 changes: 3 additions & 3 deletions src/UIPlatformTest/NirnLabUIPlatformAPI/API.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ namespace NL::UI

/// <summary>
/// Response with version info. See ResponseVersionMessage struct.
/// You should check current API version (APIVersion::AS_INT) and version in response.
/// You should check current API version (NL::UI::APIVersion::AS_INT) and version in response.
/// It is not guaranteed that the major versions are compatible. In this case, I recommend not using the library.
/// </summary>
ResponseVersion,
Expand All @@ -69,12 +69,12 @@ namespace NL::UI
/// <summary>
/// NirnLabUIPlatform version
/// </summary>
std::uint32_t libVersion = LibVersion::AS_INT;
std::uint32_t libVersion = NL::UI::LibVersion::AS_INT;

/// <summary>
/// NirnLabUIPlatform API version
/// </summary>
std::uint32_t apiVersion = APIVersion::AS_INT;
std::uint32_t apiVersion = NL::UI::APIVersion::AS_INT;
};

struct ResponseAPIMessage
Expand Down
16 changes: 8 additions & 8 deletions src/UIPlatformTest/NirnLabUIPlatformAPI/Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

#include <cstdint>

namespace LibVersion
namespace NL::UI::LibVersion
{
inline constexpr std::uint32_t MAJOR = 0;
inline constexpr std::uint32_t MINOR = 1;
inline constexpr std::uint32_t MAJOR = 1;
inline constexpr std::uint32_t MINOR = 0;
inline constexpr auto PROJECT_NAME = "NirnLabUIPlatform";

inline constexpr auto MAJOR_MULT = 100000;
inline constexpr auto AS_STRING = "0.1";
inline constexpr auto AS_STRING = "1.0";
inline constexpr std::uint32_t AS_INT = (static_cast<std::uint32_t>(MAJOR * MAJOR_MULT + MINOR));

inline std::uint32_t GetMajorVersion(std::uint32_t a_version)
Expand All @@ -23,13 +23,13 @@ namespace LibVersion
}
}

namespace APIVersion
namespace NL::UI::APIVersion
{
inline constexpr std::uint32_t MAJOR = 0;
inline constexpr std::uint32_t MINOR = 1;
inline constexpr std::uint32_t MAJOR = 1;
inline constexpr std::uint32_t MINOR = 0;

inline constexpr auto MAJOR_MULT = 100000;
inline constexpr auto AS_STRING = "0.1";
inline constexpr auto AS_STRING = "1.0";
inline constexpr std::uint32_t AS_INT = (static_cast<std::uint32_t>(MAJOR * MAJOR_MULT + MINOR));

inline std::uint32_t GetMajorVersion(std::uint32_t a_version)
Expand Down
28 changes: 14 additions & 14 deletions src/UIPlatformTest/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,46 +55,46 @@ SKSEPluginLoad(const SKSE::LoadInterface* a_skse)
{
case SKSE::MessagingInterface::kPostPostLoad:
// All plugins are loaded. Request lib version.
SKSE::GetMessagingInterface()->Dispatch(NL::UI::APIMessageType::RequestVersion, nullptr, 0, LibVersion::PROJECT_NAME);
SKSE::GetMessagingInterface()->Dispatch(NL::UI::APIMessageType::RequestVersion, nullptr, 0, NL::UI::LibVersion::PROJECT_NAME);
break;
case SKSE::MessagingInterface::kInputLoaded:
if (g_canUseAPI)
{
// API version is ok. Request interface.
SKSE::GetMessagingInterface()->Dispatch(NL::UI::APIMessageType::RequestAPI, nullptr, 0, LibVersion::PROJECT_NAME);
SKSE::GetMessagingInterface()->Dispatch(NL::UI::APIMessageType::RequestAPI, nullptr, 0, NL::UI::LibVersion::PROJECT_NAME);
}
break;
default:
break;
}
});
SKSE::GetMessagingInterface()->RegisterListener(nullptr, [](SKSE::MessagingInterface::Message* a_msg) {
SKSE::GetMessagingInterface()->RegisterListener(NL::UI::LibVersion::PROJECT_NAME, [](SKSE::MessagingInterface::Message* a_msg) {
spdlog::info("Received message({}) from \"{}\"", a_msg->type, a_msg->sender ? a_msg->sender : "nullptr");
switch (a_msg->type)
{
case NL::UI::APIMessageType::ResponseVersion: {
const auto versionInfo = reinterpret_cast<NL::UI::ResponseVersionMessage*>(a_msg->data);
spdlog::info("NirnLabUIPlatform version: {}.{}", LibVersion::GetMajorVersion(versionInfo->libVersion), LibVersion::GetMinorVersion(versionInfo->libVersion));
spdlog::info("NirnLabUIPlatform version: {}.{}", NL::UI::LibVersion::GetMajorVersion(versionInfo->libVersion), NL::UI::LibVersion::GetMinorVersion(versionInfo->libVersion));

const auto majorAPIVersion = APIVersion::GetMajorVersion(versionInfo->apiVersion);
const auto majorAPIVersion = NL::UI::APIVersion::GetMajorVersion(versionInfo->apiVersion);
// If the major version is different from ours, then using the API may cause problems
if (majorAPIVersion != APIVersion::MAJOR)
if (majorAPIVersion != NL::UI::APIVersion::MAJOR)
{
g_canUseAPI = false;
spdlog::error("Can't using this API version of NirnLabUIPlatform. We have {}.{} and installed is {}.{}",
APIVersion::MAJOR,
APIVersion::MINOR,
APIVersion::GetMajorVersion(versionInfo->apiVersion),
APIVersion::GetMinorVersion(versionInfo->apiVersion));
NL::UI::APIVersion::MAJOR,
NL::UI::APIVersion::MINOR,
NL::UI::APIVersion::GetMajorVersion(versionInfo->apiVersion),
NL::UI::APIVersion::GetMinorVersion(versionInfo->apiVersion));
}
else
{
g_canUseAPI = true;
spdlog::info("API version is ok. We have {}.{} and installed is {}.{}",
APIVersion::MAJOR,
APIVersion::MINOR,
APIVersion::GetMajorVersion(versionInfo->apiVersion),
APIVersion::GetMinorVersion(versionInfo->apiVersion));
NL::UI::APIVersion::MAJOR,
NL::UI::APIVersion::MINOR,
NL::UI::APIVersion::GetMajorVersion(versionInfo->apiVersion),
NL::UI::APIVersion::GetMinorVersion(versionInfo->apiVersion));
}
break;
}
Expand Down
4 changes: 2 additions & 2 deletions src/UIPlugin/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@ static inline TFunc ExecLibFunc(const char* a_funcName)

extern "C" DLLEXPORT constinit auto SKSEPlugin_Version = []() {
SKSE::PluginVersionData v{};
v.pluginVersion = LibVersion::AS_INT;
v.PluginName(LibVersion::PROJECT_NAME);
v.pluginVersion = NL::UI::LibVersion::AS_INT;
v.PluginName(NL::UI::LibVersion::PROJECT_NAME);
v.AuthorName("kkEngine"sv);
v.CompatibleVersions({SKSE::RUNTIME_SSE_1_6_640, REL::Version(1, 6, 1170, 0)});
v.UsesAddressLibrary(true);
Expand Down
4 changes: 2 additions & 2 deletions src/Version.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include <cstdint>

namespace LibVersion
namespace NL::UI::LibVersion
{
inline constexpr std::uint32_t MAJOR = @PROJECT_VERSION_MAJOR@;
inline constexpr std::uint32_t MINOR = @PROJECT_VERSION_MINOR@;
Expand All @@ -23,7 +23,7 @@ namespace LibVersion
}
}

namespace APIVersion
namespace NL::UI::APIVersion
{
inline constexpr std::uint32_t MAJOR = @API_MAJOR_VERSION@;
inline constexpr std::uint32_t MINOR = @API_MINOR_VERSION@;
Expand Down

0 comments on commit 7ea5df3

Please sign in to comment.