chore: checkpoint web Blender feature-gap work, docs and tests
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

- update native web_engine sources and rebuilt wasm artifacts
- add task cards, status notes and tooling scripts
- add web e2e specs, tutorial UI sources and tutorial assets
- sync golden task manifests and audit records

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
mes123456
2026-11-11 10:46:55 +08:00
parent f3e21c6b98
commit d1e6b63d54
665 changed files with 59149 additions and 39194 deletions

View File

@@ -4,6 +4,7 @@
set(INC
../include
../../blenloader
../../ikplugin
../../makesrna
../../modifiers

View File

@@ -50,6 +50,7 @@
#include "BKE_action.hh"
#include "BKE_anim_data.hh"
#include "BKE_appdir.hh"
#include "BKE_anonymous_attribute_id.hh"
#include "BKE_armature.hh"
#include "BKE_attribute.h"
@@ -114,6 +115,8 @@
#include "UI_interface_icons.hh"
#include "UI_interface_layout.hh"
#include "BLO_readfile.hh"
#include "WM_api.hh"
#include "WM_types.hh"
@@ -2352,12 +2355,53 @@ static NodesModifierData *add_essential_asset_modifier(bContext &C,
* automatically during user interaction). */
asset::list::storage_fetch_blocking(asset_system::all_library_reference(), C);
}
#ifdef WITH_WEB
/* The browser session has no interactive Asset Browser pass to list the
* embedded Essentials assets first; fetch the small bundle on demand. */
asset::list::storage_fetch_blocking(asset_system::all_library_reference(), C);
#endif
#ifdef WITH_WEB
/* A missing index entry is expected for the embedded FS; the direct append
* below is the authoritative fallback, so don't record a false error. */
const asset_system::AssetRepresentation *asset_representation = asset::find_asset_from_weak_ref(
C, asset_weak_ref, nullptr);
#else
const asset_system::AssetRepresentation *asset_representation = asset::find_asset_from_weak_ref(
C, asset_weak_ref, reports);
if (!asset_representation) {
return nullptr;
#endif
ID *asset_id = asset_representation ?
asset::asset_local_id_ensure_imported(bmain, *asset_representation) :
nullptr;
#ifdef WITH_WEB
if (!asset_id) {
/* The embedded Essentials bundle is readable, but the file-based asset
* listing does not index files inside the packaged WebAssembly FS. Append
* the requested node group directly from the embedded .blend instead. */
const std::string asset_path = path.c_str();
const size_t blend_pos = asset_path.find(".blend/");
const size_t type_pos = blend_pos == std::string::npos ? std::string::npos :
asset_path.find('/', blend_pos + 7);
const std::optional<std::string> assets_dir = BKE_appdir_folder_id(BLENDER_SYSTEM_DATAFILES,
"assets");
if (blend_pos != std::string::npos && type_pos != std::string::npos && assets_dir) {
const std::string filepath = *assets_dir + "/" + asset_path.substr(0, blend_pos + 6);
const std::string type_name = asset_path.substr(blend_pos + 7, type_pos - (blend_pos + 7));
const std::string id_name = asset_path.substr(type_pos + 1);
if (type_name == "NodeTree") {
asset_id = WM_file_append_datablock(&bmain,
&scene,
CTX_data_view_layer(&C),
nullptr,
filepath.c_str(),
ID_NT,
id_name.c_str(),
BLO_LIBLINK_APPEND_RECURSIVE |
BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR,
reports);
}
}
}
ID *asset_id = asset::asset_local_id_ensure_imported(bmain, *asset_representation);
#endif
if (!asset_id) {
return nullptr;
}

View File

@@ -11,6 +11,7 @@
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <optional>
#include "AS_asset_library.hh"
#include "BLI_path_utils.hh"
@@ -37,6 +38,7 @@
#include "DNA_scene_types.h"
#include "BKE_anim_visualization.h"
#include "BKE_appdir.hh"
#include "BKE_armature.hh"
#include "BKE_collection.hh"
#include "BKE_constraint.h"
@@ -68,6 +70,8 @@
#include "BKE_softbody.h"
#include "BKE_workspace.hh"
#include "BLO_readfile.hh"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_build.hh"
@@ -1867,13 +1871,42 @@ static wmOperatorStatus shade_auto_smooth_exec(bContext *C, wmOperator *op)
asset::list::storage_fetch_blocking(asset_system::all_library_reference(), *C);
}
#ifdef WITH_WEB
/* The browser session has no interactive Asset Browser pass to list the
* embedded Essentials bundle; fetch it and fall back to a direct append. */
asset::list::storage_fetch_blocking(asset_system::all_library_reference(), *C);
const asset_system::AssetRepresentation *asset_representation =
asset::find_asset_from_weak_ref(*C, asset_weak_ref, nullptr);
bNodeTree *node_group = nullptr;
if (!asset_representation) {
const std::optional<std::string> assets_dir = BKE_appdir_folder_id(
BLENDER_SYSTEM_DATAFILES, "assets");
if (!assets_dir) {
return OPERATOR_CANCELLED;
}
ID *node_group_id = WM_file_append_datablock(
&bmain, &scene, CTX_data_view_layer(C), nullptr,
(*assets_dir + "/nodes/geometry_nodes_essentials.blend").c_str(), ID_NT,
"Smooth by Angle",
BLO_LIBLINK_APPEND_RECURSIVE | BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR,
op->reports);
if (!node_group_id || GS(node_group_id->name) != ID_NT) {
return OPERATOR_CANCELLED;
}
node_group = reinterpret_cast<bNodeTree *>(node_group_id);
node_group->ensure_topology_cache();
if (!is_valid_smooth_by_angle_group(*node_group)) {
return OPERATOR_CANCELLED;
}
}
#else
const asset_system::AssetRepresentation *asset_representation =
asset::find_asset_from_weak_ref(*C, asset_weak_ref, op->reports);
if (!asset_representation) {
return OPERATOR_CANCELLED;
}
bNodeTree *node_group = nullptr;
#endif
while (!node_group) {
ID *node_group_id = asset::asset_local_id_ensure_imported(bmain, *asset_representation);
if (!node_group_id) {