[Bf-blender-cvs] [ce9949f7fa6] blender-projects-basics: Support active project, set when loading or writing a file (+ tests)
Julian Eisel
noreply at git.blender.org
Thu Sep 29 14:37:34 CEST 2022
Commit: ce9949f7fa689e8d9d0c12894fb973cd1da2fffe
Author: Julian Eisel
Date: Thu Sep 29 14:25:54 2022 +0200
Branches: blender-projects-basics
https://developer.blender.org/rBce9949f7fa689e8d9d0c12894fb973cd1da2fffe
Support active project, set when loading or writing a file (+ tests)
The active project is determined via the path of the .blend file. So if
that changes (on write) or when a new .blend file is opend, the active
project is updated.
Some of the added tests require a latest checkout of the libraries SVN
repository (see rBL63043).
===================================================================
A source/blender/blenkernel/BKE_blender_project.h
R055 source/blender/blenkernel/BKE_project_settings.hh source/blender/blenkernel/BKE_blender_project.hh
M source/blender/blenkernel/BKE_context.h
M source/blender/blenkernel/CMakeLists.txt
A source/blender/blenkernel/intern/blender_project.cc
R062 source/blender/blenkernel/intern/project_settings_test.cc source/blender/blenkernel/intern/blender_project_test.cc
M source/blender/blenkernel/intern/blendfile.c
M source/blender/blenkernel/intern/context.c
D source/blender/blenkernel/intern/project_settings.cc
M source/blender/blenloader/intern/writefile.cc
===================================================================
diff --git a/source/blender/blenkernel/BKE_blender_project.h b/source/blender/blenkernel/BKE_blender_project.h
new file mode 100644
index 00000000000..8fdda3e18ea
--- /dev/null
+++ b/source/blender/blenkernel/BKE_blender_project.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/** \file
+ * \ingroup bke
+ */
+
+#pragma once
+
+#include "DNA_space_types.h"
+
+#include "BLI_compiler_attrs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* C-handle for #bke::BlenderProject. */
+typedef struct BlenderProject BlenderProject;
+
+BlenderProject *BKE_project_active_get(void) ATTR_WARN_UNUSED_RESULT;
+/**
+ * \note: When unsetting an active project, the previously active one will be destroyed, so
+ * pointers may dangle.
+ */
+void BKE_project_active_unset(void);
+/**
+ * Attempt to load and activate a project based on the given path. If the path doesn't lead into a
+ * project, the active project is unset. Note that the project will be unset on any failure when
+ * loading the project.
+ *
+ * \note: When setting an active project, the previously active one will be destroyed, so pointers
+ * may dangle.
+ */
+BlenderProject *BKE_project_active_load_from_path(const char *path) ATTR_NONNULL();
+
+const char *BKE_project_root_path_get(const BlenderProject *project) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/blenkernel/BKE_project_settings.hh b/source/blender/blenkernel/BKE_blender_project.hh
similarity index 55%
rename from source/blender/blenkernel/BKE_project_settings.hh
rename to source/blender/blenkernel/BKE_blender_project.hh
index 646a38196bb..9f775009aff 100644
--- a/source/blender/blenkernel/BKE_project_settings.hh
+++ b/source/blender/blenkernel/BKE_blender_project.hh
@@ -12,6 +12,34 @@
namespace blender::bke {
+class ProjectSettings;
+
+class BlenderProject {
+ inline static std::unique_ptr<BlenderProject> instance_;
+
+ std::unique_ptr<ProjectSettings> settings_;
+
+ public:
+ static auto get_active [[nodiscard]] () -> BlenderProject *;
+ static auto set_active_from_settings(std::unique_ptr<ProjectSettings> settings)
+ -> BlenderProject *;
+
+ /**
+ * Check if \a path points into a project and return the root directory path of that project (the
+ * one containing the .blender_project directory). Walks "upwards" through the path and returns
+ * the first project found, so if a project is nested inside another one, the nested project is
+ * used.
+ * Both Unix and Windows style slashes are allowed.
+ * \return the project root path or an empty path if not found.
+ */
+ static auto project_root_path_find_from_path [[nodiscard]] (StringRef path) -> StringRef;
+
+ auto get_settings [[nodiscard]] () const -> ProjectSettings &;
+
+ private:
+ explicit BlenderProject(std::unique_ptr<ProjectSettings> settings);
+};
+
class ProjectSettings {
/* Path to the project root using slashes in the OS native format. */
std::string project_root_path_;
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index b7068720469..f3edce7709c 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -22,6 +22,7 @@ extern "C" {
struct ARegion;
struct Base;
+struct BlenderProject;
struct CacheFile;
struct Collection;
struct Depsgraph;
@@ -173,6 +174,7 @@ struct ARegion *CTX_wm_menu(const bContext *C);
struct wmGizmoGroup *CTX_wm_gizmo_group(const bContext *C);
struct wmMsgBus *CTX_wm_message_bus(const bContext *C);
struct ReportList *CTX_wm_reports(const bContext *C);
+struct BlenderProject *CTX_wm_project(void);
struct View3D *CTX_wm_view3d(const bContext *C);
struct RegionView3D *CTX_wm_region_view3d(const bContext *C);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 5d8f19fe009..02f604b657c 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -81,6 +81,7 @@ set(SRC
intern/autoexec.c
intern/blender.c
intern/blender_copybuffer.c
+ intern/blender_project.cc
intern/blender_undo.c
intern/blender_user_menu.c
intern/blendfile.c
@@ -254,7 +255,6 @@ set(SRC
intern/pointcache.c
intern/pointcloud.cc
intern/preferences.c
- intern/project_settings.cc
intern/report.c
intern/rigidbody.c
intern/scene.cc
@@ -330,6 +330,8 @@ set(SRC
BKE_autoexec.h
BKE_blender.h
BKE_blender_copybuffer.h
+ BKE_blender_project.h
+ BKE_blender_project.hh
BKE_blender_undo.h
BKE_blender_user_menu.h
BKE_blender_version.h
@@ -454,7 +456,6 @@ set(SRC
BKE_pointcache.h
BKE_pointcloud.h
BKE_preferences.h
- BKE_project_settings.hh
BKE_report.h
BKE_rigidbody.h
BKE_scene.h
@@ -835,6 +836,7 @@ if(WITH_GTESTS)
intern/asset_library_service_test.cc
intern/asset_library_test.cc
intern/asset_test.cc
+ intern/blender_project_test.cc
intern/bpath_test.cc
intern/cryptomatte_test.cc
intern/curves_geometry_test.cc
@@ -847,11 +849,11 @@ if(WITH_GTESTS)
intern/lib_id_remapper_test.cc
intern/lib_id_test.cc
intern/lib_remap_test.cc
- intern/project_settings_test.cc
intern/tracking_test.cc
)
set(TEST_INC
../editors/include
+ ../blenloader/tests
)
include(GTestTesting)
blender_add_test_lib(bf_blenkernel_tests "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/blenkernel/intern/blender_project.cc b/source/blender/blenkernel/intern/blender_project.cc
new file mode 100644
index 00000000000..8016b78fd81
--- /dev/null
+++ b/source/blender/blenkernel/intern/blender_project.cc
@@ -0,0 +1,175 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "BKE_blender_project.h"
+#include "BKE_blender_project.hh"
+
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+
+#include "DNA_space_types.h"
+
+#include "BLI_fileops.h"
+#include "BLI_path_util.h"
+
+namespace blender::bke {
+
+static StringRef path_strip_trailing_native_slash(StringRef path);
+static bool path_contains_project_settings(StringRef path);
+
+BlenderProject::BlenderProject(std::unique_ptr<ProjectSettings> settings)
+ : settings_(std::move(settings))
+{
+}
+
+BlenderProject *BlenderProject::set_active_from_settings(std::unique_ptr<ProjectSettings> settings)
+{
+ if (settings) {
+ instance_ = std::make_unique<BlenderProject>(BlenderProject(std::move(settings)));
+ }
+ else {
+ instance_ = nullptr;
+ }
+
+ return instance_.get();
+}
+
+BlenderProject *BlenderProject::get_active()
+{
+ return instance_.get();
+}
+
+StringRef BlenderProject::project_root_path_find_from_path(StringRef path)
+{
+ std::string path_native = path;
+ BLI_path_slash_native(path_native.data());
+
+ StringRef cur_path = path;
+
+ while (cur_path.size()) {
+ std::string pa = StringRef(path_native.c_str(), cur_path.size());
+ if (bke::path_contains_project_settings(pa)) {
+ return path.substr(0, cur_path.size());
+ }
+
+ /* Walk "up the path" (check the parent next). */
+ const int64_t pos_last_slash = cur_path.find_last_of(SEP);
+ if (pos_last_slash == StringRef::not_found) {
+ break;
+ }
+ cur_path = cur_path.substr(0, pos_last_slash);
+ }
+
+ return "";
+}
+
+ProjectSettings &BlenderProject::get_settings() const
+{
+ BLI_assert(settings_ != nullptr);
+ return *settings_;
+}
+
+/* ---------------------------------------------------------------------- */
+
+ProjectSettings::ProjectSettings(StringRef project_root_path)
+ : project_root_path_(project_root_path)
+{
+}
+
+bool ProjectSettings::create_settings_directory(StringRef project_root_path)
+{
+ std::string project_root_path_native = project_root_path;
+ BLI_path_slash_native(project_root_path_native.data());
+
+ return BLI_dir_create_recursive(
+ std::string(project_root_path_native + SEP + SETTINGS_DIRNAME).c_str());
+}
+
+static StringRef path_strip_trailing_native_slash(StringRef path)
+{
+ const int64_t pos_before_trailing_slash = path.find_last_not_of(SEP);
+ return (pos_before_trailing_slash == StringRef::not_found) ?
+ path :
+ path.substr(0, pos_before_trailing_slash + 1);
+}
+
+static bool path_contains_project_settings(StringRef path)
+{
+ path = path_strip_trailing_native_slash(path);
+ return BLI_exists(std::string(path + SEP_STR + ProjectSettings::SETTINGS_DIRNAME).c_str());
+}
+
+std::unique_ptr<ProjectSettings> ProjectSettings::load_from_disk(StringRef project_path)
+{
+ std::string project_path_native = project_path;
+ BLI_path_slash_native(project_path_native.data());
+
+ if (!BLI_exists(project_path_native.c_str())) {
+ return nullptr;
+ }
+
+ StringRef project_root_path = project_path_native;
+
+ const StringRef path_no_trailing_slashes = path_strip_trailing_native_slash(project_path_native);
+ if (path_no_trailing_slashes.endswith(SETTINGS_DIRNAME)) {
+ project_root_path = StringRef(project_path_native).drop_suffix(SETTINGS_DIRNAME.size() + 1);
+ }
+
+ if (!path_contains_project_settings(project_root_path)) {
+ return nullptr;
+ }
+
+ return std::make_unique<ProjectSettings>(project_root_path);
+}
+
+StringRefNull ProjectSettings::project_root_path() const
+{
+ return project_root_path_;
+}
+
+} // namespace blender::bke
+
+/* ---------------------------------------------------------------------- */
+
+using namespace blender;
+
+BlenderProject *BKE_project_active_get(void)
+{
+ return reinterpret_cast<BlenderProject *>(bke::BlenderProject::get_active());
+}
+
+void BKE_project_active_unset(void)
+{
+ bke::BlenderProject::set_active_from_settings(nullptr);
+}
+
+BlenderProject *BKE_project_active_load_from_path(const char *path)
+{
+ /* Project should be unset if the path doesn't contain a project root. Unset in the beginning so
+ * early exiting behaves correctly. */
+ BKE_project_active_unset();
+
+ StringRef project_root = bke::BlenderProject::project_root_path_find_from_path(path);
+ if (project_root.is_empty()) {
+ return nullptr;
+ }
+
+ std::unique_ptr project_settings = bke::ProjectSettings::load_from_disk(project_root);
+ if (!project
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list