Set default project name & add default asset library

Default project name will just be the directory name. The default asset
library will be called "Project Library" and point to an `assets/`
directory inside the project root directory.
This commit is contained in:
Julian Eisel 2022-10-13 18:58:05 +02:00
parent 1f819df7df
commit 97f667058c
10 changed files with 141 additions and 21 deletions

View File

@ -36,8 +36,9 @@ void BKE_asset_library_custom_name_set(struct ListBase *custom_libraries,
/**
* Set the library path, ensuring it is pointing to a directory.
* Single blend files can only act as "Current File" library; libraries on disk
* should always be directories. If the path does not exist, that's fine; it can
* created as directory if necessary later.
* should always be directories. Blindly sets the path without additional checks. The asset system
* can ignore libraries that it can't resolve to a valid location. If the path does not exist,
* that's fine; it can created as directory if necessary later.
*/
void BKE_asset_library_custom_path_set(struct CustomAssetLibraryDefinition *library,
const char *path) ATTR_NONNULL();

View File

@ -38,6 +38,19 @@ bool BKE_project_is_path_project_root(const char *path) ATTR_WARN_UNUSED_RESULT
* referenced file/directory is a project root directory).
*/
bool BKE_project_contains_path(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/**
* Attempt to load project based on the given path and return it. This should never become the
* active project, which should be loaded with #BKE_project_active_load_from_path() instead
* (because the active project uses unique_ptr without the guarded allocator, unlike this C-API
* function). The returned project pointer is owning and needs freeing with #BKE_project_free().
*/
BlenderProject *BKE_project_load_from_path(const char *path) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
/**
* Free a project allocated by #BKE_project_load_from_path() and null the pointer to it.
*/
void BKE_project_free(BlenderProject **project) ATTR_NONNULL();
/**
* 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

View File

@ -12,6 +12,8 @@
#include "BLI_string_ref.hh"
#include "BLI_utility_mixins.hh"
struct BlenderProject;
namespace blender::io::serialize {
class DictionaryValue;
}
@ -39,10 +41,11 @@ class BlenderProject {
*/
static auto project_root_path_find_from_path [[nodiscard]] (StringRef path) -> StringRef;
explicit BlenderProject(std::unique_ptr<ProjectSettings> settings);
auto get_settings [[nodiscard]] () const -> ProjectSettings &;
private:
explicit BlenderProject(std::unique_ptr<ProjectSettings> settings);
static std::unique_ptr<BlenderProject> &active_project_ptr();
};
@ -83,6 +86,13 @@ class ProjectSettings {
*/
static auto load_from_disk [[nodiscard]] (StringRef project_path)
-> std::unique_ptr<ProjectSettings>;
/**
* Read project settings from the given \a path, which may point to some directory or file inside
* of the project directory. Both Unix and Windows style slashes are allowed. Path is expected to
* be normalized.
* \return The read project settings or null in case of failure.
*/
static auto load_from_path [[nodiscard]] (StringRef path) -> std::unique_ptr<ProjectSettings>;
/**
* Write project settings to the given \a project_path, which may be either a project root
* directory or the .blender_project directory. The .blender_project directory must exist.

View File

@ -30,6 +30,8 @@
#include "BKE_asset_library_custom.h"
using namespace blender;
/* -------------------------------------------------------------------- */
/** \name Asset Libraries
* \{ */
@ -75,9 +77,6 @@ void BKE_asset_library_custom_name_set(ListBase *custom_libraries,
void BKE_asset_library_custom_path_set(CustomAssetLibraryDefinition *library, const char *path)
{
BLI_strncpy(library->path, path, sizeof(library->path));
if (BLI_is_file(library->path)) {
BLI_path_parent_dir(library->path);
}
}
CustomAssetLibraryDefinition *BKE_asset_library_custom_find_from_index(

View File

@ -190,6 +190,8 @@ static std::unique_ptr<ExtractedSettings> extract_settings(
"Unexpected asset_library entry in settings.json, expected path to be string");
}
/* TODO this isn't really extracting, should be creating data from the settings be a
* separate step? */
CustomAssetLibraryDefinition *library = BKE_asset_library_custom_add(
&extracted_settings->asset_libraries);
/* Name or path may not be set, this is fine. */
@ -267,6 +269,16 @@ std::unique_ptr<ProjectSettings> ProjectSettings::load_from_disk(StringRef proje
return loaded_settings;
}
std::unique_ptr<ProjectSettings> ProjectSettings::load_from_path(StringRef path)
{
StringRef project_root = bke::BlenderProject::project_root_path_find_from_path(path);
if (project_root.is_empty()) {
return nullptr;
}
return bke::ProjectSettings::load_from_disk(project_root);
}
std::unique_ptr<serialize::DictionaryValue> ProjectSettings::to_dictionary() const
{
using namespace serialize;
@ -448,22 +460,36 @@ bool BKE_project_contains_path(const char *path)
return !found_root_path.is_empty();
}
BlenderProject *BKE_project_load_from_path(const char *path)
{
std::unique_ptr<bke::ProjectSettings> project_settings = bke::ProjectSettings::load_from_path(
path);
if (!project_settings) {
return nullptr;
}
return reinterpret_cast<BlenderProject *>(
MEM_new<bke::BlenderProject>(__func__, std::move(project_settings)));
}
void BKE_project_free(BlenderProject **project_handle)
{
bke::BlenderProject *project = reinterpret_cast<bke::BlenderProject *>(*project_handle);
BLI_assert_msg(project != bke::BlenderProject::get_active(),
"Projects loaded with #BKE_project_load_from_path() must never be set active.");
MEM_delete(project);
*project_handle = 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_settings) {
return nullptr;
}
std::unique_ptr<bke::ProjectSettings> project_settings = bke::ProjectSettings::load_from_path(
path);
bke::BlenderProject::set_active_from_settings(std::move(project_settings));
return BKE_project_active_get();

View File

@ -12,8 +12,14 @@
extern "C" {
#endif
struct BlenderProject;
void ED_operatortypes_project(void);
/** Sets the project name to the directory name it is located in and registers a "Project Library"
* asset library pointing to `//assets/`. */
void ED_project_set_defaults(struct BlenderProject *project);
#ifdef __cplusplus
}
#endif

View File

@ -6,6 +6,7 @@ set(INC
../include
../../blenkernel
../../blenlib
../../blentranslation
../../makesdna
../../makesrna
../../windowmanager
@ -16,6 +17,7 @@ set(INC_SYS
)
set(SRC
project.cc
project_ops.cc
)

View File

@ -0,0 +1,38 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edproject
*/
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_string_ref.hh"
#include "BLT_translation.h"
#include "BKE_asset_library_custom.h"
#include "BKE_blender_project.h"
#include "ED_project.h"
using namespace blender;
/** Name of the asset library added by default. Needs translation with `DATA_()`. */
inline static const char *DEFAULT_ASSET_LIBRARY_NAME = N_("Project Library");
inline static const char *DEFAULT_ASSET_LIBRARY_PATH = "//assets/";
void ED_project_set_defaults(BlenderProject *project)
{
char project_root_dir[FILE_MAXDIR];
BLI_strncpy(project_root_dir, BKE_project_root_path_get(project), sizeof(project_root_dir));
/* Set directory name as default project name. */
char dirname[FILE_MAXFILE];
BLI_path_slash_rstrip(project_root_dir);
BLI_split_file_part(project_root_dir, dirname, sizeof(dirname));
BKE_project_name_set(project, dirname);
ListBase *libraries = BKE_project_custom_asset_libraries_get(project);
BKE_asset_library_custom_add(
libraries, DATA_(DEFAULT_ASSET_LIBRARY_NAME), DEFAULT_ASSET_LIBRARY_PATH);
}

View File

@ -283,7 +283,12 @@ static void rna_CustomAssetLibraryDefinition_path_set(PointerRNA *ptr, const cha
return;
}
BKE_asset_library_custom_path_set(library, value);
char dirpath[FILE_MAX];
BLI_strncpy(dirpath, value, sizeof(dirpath));
if (BLI_is_file(dirpath)) {
BLI_path_parent_dir(dirpath);
}
BKE_asset_library_custom_path_set(library, dirpath);
}
void rna_AssetLibrary_settings_update(Main *UNUSED(bmain),

View File

@ -97,6 +97,7 @@
#include "ED_fileselect.h"
#include "ED_image.h"
#include "ED_outliner.h"
#include "ED_project.h"
#include "ED_render.h"
#include "ED_screen.h"
#include "ED_undo.h"
@ -2408,12 +2409,15 @@ static int wm_new_project_exec(bContext *C, wmOperator *op)
BKE_reportf(op->reports, RPT_INFO, "Project created and loaded successfully");
bool activated_new_project = false;
if (blendfile_path[0] && BLI_path_contains(project_root_dir, blendfile_path)) {
BKE_project_active_load_from_path(blendfile_path);
if (BKE_project_active_load_from_path(blendfile_path)) {
activated_new_project = true;
WM_main_add_notifier(NC_PROJECT, NULL);
/* Update the window title. */
WM_event_add_notifier_ex(CTX_wm_manager(C), CTX_wm_window(C), NC_WM | ND_DATACHANGED, NULL);
WM_main_add_notifier(NC_PROJECT, NULL);
/* Update the window title. */
WM_event_add_notifier_ex(CTX_wm_manager(C), CTX_wm_window(C), NC_WM | ND_DATACHANGED, NULL);
}
}
else {
BKE_reportf(op->reports,
@ -2422,6 +2426,22 @@ static int wm_new_project_exec(bContext *C, wmOperator *op)
"project is not active");
}
/* Some default settings for the project. It has to be loaded for that. */
BlenderProject *new_project = activated_new_project ?
CTX_wm_project() :
BKE_project_load_from_path(project_root_dir);
if (new_project) {
ED_project_set_defaults(new_project);
/* Write defaults to the hard drive. */
BKE_project_settings_save(new_project);
/* We just temporary loaded the project, free it again. */
if (!activated_new_project) {
BKE_project_free(&new_project);
}
}
PropertyRNA *prop_open_settings = RNA_struct_find_property(op->ptr, "open_settings_after");
if (RNA_property_is_set(op->ptr, prop_open_settings) &&
RNA_property_boolean_get(op->ptr, prop_open_settings)) {