Polyphase Game Engine
Loading...
Searching...
No Matches
AddonManager.h
Go to the documentation of this file.
1#pragma once
2
3#if EDITOR
4
5#include "../ProjectSelect/TemplateData.h"
6#include <string>
7#include <vector>
8
15class AddonManager
16{
17public:
18 static void Create();
19 static void Destroy();
20 static AddonManager* Get();
21
23 std::string GetAddonCacheDirectory();
24
26 std::string GetSettingsPath();
27
29 std::string GetInstalledAddonsPath();
30
31 // Repository management
32 void LoadSettings();
33 void SaveSettings();
34 void AddRepository(const std::string& url);
35 void RemoveRepository(const std::string& url);
36 const std::vector<AddonRepository>& GetRepositories() const { return mRepositories; }
37
38 // Addon discovery
39 void RefreshAllRepositories();
40 void RefreshRepository(const std::string& url);
41 // True once RefreshAllRepositories has run this session. The dependency
42 // resolver uses it to refresh lazily when a dependency lookup misses at
43 // project load, before the Addons window has ever been opened.
44 bool HasRefreshedRepositories() const { return mRepositoriesRefreshed; }
45 const std::vector<Addon>& GetAvailableAddons() const { return mAvailableAddons; }
46 const std::vector<AddonCategory>& GetCategories() const { return mCategories; }
47
48 // Installation
49 bool DownloadAddon(const Addon& addon, std::string& outError);
50 // source (optional) is stamped onto the InstalledAddon record so update
51 // checks and re-downloads know the repo/branch/commit the files came from.
52 bool InstallAddon(const std::string& addonCachePath, const std::string& addonId, std::string& outError,
53 const AddonInstallSource* source = nullptr);
54 // Dependencies declared by the most recently installed addon that are
55 // still absent from Packages/ after auto-resolution. Empty on success.
56 const std::vector<std::string>& GetLastInstallMissingDependencies() const { return mLastInstallMissingDeps; }
57 // Deletes Packages/<id> and Intermediate/Plugins/<id>, drops the record.
58 // Does not unload a native DLL or check dependents — the Addons window
59 // handles both before calling this (see ProcessPendingUninstalls).
60 bool UninstallAddon(const std::string& addonId);
61
62 // Fetch an addon from an arbitrary URL (GitHub repo or direct .zip), unzip it,
63 // and install into the current project's Packages/. Used by the dependency resolver.
64 bool DownloadAndInstallFromUrl(const std::string& addonId,
65 const std::string& url,
66 const std::string& ref,
67 std::string& outError);
68
69 // Auto-resolve declared dependencies on install / project load.
70 bool GetAutoResolveDependencies() const { return mAutoResolveDeps; }
71 void SetAutoResolveDependencies(bool v) { mAutoResolveDeps = v; SaveSettings(); }
72
73 // Tracking
74 void LoadInstalledAddons();
75 void SaveInstalledAddons();
76 const std::vector<InstalledAddon>& GetInstalledAddons() const { return mInstalledAddons; }
77 std::vector<InstalledAddon>& GetInstalledAddonsMutable() { return mInstalledAddons; }
78 bool IsAddonInstalled(const std::string& addonId) const;
79 const InstalledAddon* FindInstalled(const std::string& addonId) const;
80 // True when GetUpdateStatus reports NewCommits or NewVersion.
81 bool HasUpdate(const std::string& addonId) const;
82 // Combines the registry version (secondary) with the branch head commit
83 // recorded by the last CheckForUpdates (primary). See AddonUpdateStatus.
84 AddonUpdateStatus GetUpdateStatus(const std::string& addonId) const;
85 std::string GetInstalledVersion(const std::string& addonId) const;
86
87 // Update checks. Synchronous network calls — run from the end-of-frame
88 // dispatcher under EditorProgress, never from an ImGui draw.
89 //
90 // FetchLatestCommit resolves the newest commit on <branch> touching
91 // <subPath> (empty = whole repo) through the GitHub API. Non-GitHub
92 // hosts fail with an explanatory error.
93 bool FetchLatestCommit(const std::string& repoUrl, const std::string& branch,
94 const std::string& subPath, std::string& outSha,
95 std::string& outDate, std::string& outError);
96 // Refreshes the registry, then stamps mRemoteCommit / mUpdateCheckError
97 // on every installed record that has a checkable source. Returns the
98 // number of addons with an update available.
99 int CheckForUpdates(std::string& outSummary);
100 // Effective branch for downloads and update checks.
101 static std::string GetAddonBranch(const Addon& addon);
102 bool SetInstalledAddonNativeMode(const std::string& addonId, NativeAddonResolveMode mode);
103 bool SyncNativeAddonBinary(const std::string& addonId, std::string& outError);
104
105 // Find addon by ID
106 const Addon* FindAddon(const std::string& addonId) const;
107
108private:
109 static AddonManager* sInstance;
110 AddonManager();
111 ~AddonManager();
112
114 void EnsureCacheDirectory();
115
124 bool FetchManifest(const std::string& url, const std::string& branch, bool& outFound);
125
126 bool FetchRepositoryManifest(const std::string& url, AddonRepository& outRepo, const std::string& branch);
128 bool FetchAddonMetadata(const std::string& repoUrl, const std::string& addonId, Addon& outAddon, const std::string& branch);
129
131 bool MergeAddonIntoProject(const std::string& addonPath, std::string& outError);
132
134 bool DownloadFile(const std::string& url, const std::string& destPath, std::string& outError);
135
137 bool ExtractZip(const std::string& zipPath, const std::string& destDir, std::string& outError);
138
139 std::string NormalizePath(const std::string& in);
140
142 std::string ConvertToRawUrl(const std::string& gitHubUrl, const std::string& filePath, const std::string& branch);
143
145 std::string ConvertToDownloadUrl(const std::string& gitHubUrl, const std::string& branch);
146
148 std::string GetCurrentTimestamp();
149
151 static bool ParseGitHubRepo(const std::string& url, std::string& outOwner, std::string& outRepo);
152
153 std::vector<AddonRepository> mRepositories;
154 std::vector<Addon> mAvailableAddons;
155 std::vector<AddonCategory> mCategories; // Registry categories from manifest.json
156 std::vector<InstalledAddon> mInstalledAddons;
157 bool mAutoResolveDeps = true;
158 bool mRepositoriesRefreshed = false;
159 std::vector<std::string> mLastInstallMissingDeps;
160};
161
162#endif