Mesh: Replace auto smooth with node group #108014
|
@ -514,7 +514,7 @@ check_spelling_shaders: .FORCE
|
|||
PYTHONIOENCODING=utf_8 $(PYTHON) \
|
||||
"$(BLENDER_DIR)/tools/check_source/check_spelling.py" \
|
||||
--cache-file=$(CHECK_SPELLING_CACHE) \
|
||||
--match=".*\.(osl|msl|glsl)$$" \
|
||||
--match=".*\.(osl|metal|msl|glsl)$$" \
|
||||
"$(BLENDER_DIR)/intern/" \
|
||||
"$(BLENDER_DIR)/source/"
|
||||
|
||||
|
|
|
@ -12,6 +12,9 @@ if(DEFINED HIP_ROOT_DIR AND HIP_ROOT_DIR)
|
|||
# Pass.
|
||||
elseif(DEFINED ENV{HIP_ROOT_DIR})
|
||||
set(HIP_ROOT_DIR $ENV{HIP_ROOT_DIR})
|
||||
elseif(DEFINED ENV{HIP_PATH})
|
||||
# Built-in environment variable from SDK.
|
||||
set(HIP_ROOT_DIR $ENV{HIP_PATH})
|
||||
else()
|
||||
set(HIP_ROOT_DIR "")
|
||||
endif()
|
||||
|
|
|
@ -12,6 +12,9 @@ if(DEFINED HIPRT_ROOT_DIR AND HIPRT_ROOT_DIR)
|
|||
# Pass.
|
||||
elseif(DEFINED ENV{HIPRT_ROOT_DIR})
|
||||
set(HIPRT_ROOT_DIR $ENV{HIPRT_ROOT_DIR})
|
||||
elseif(DEFINED ENV{HIP_PATH})
|
||||
# Built-in environment variable from SDK.
|
||||
set(HIPRT_ROOT_DIR $ENV{HIP_PATH})
|
||||
else()
|
||||
set(HIPRT_ROOT_DIR "")
|
||||
endif()
|
||||
|
@ -24,6 +27,7 @@ find_path(HIPRT_INCLUDE_DIR
|
|||
NAMES
|
||||
hiprt/hiprt.h
|
||||
HINTS
|
||||
${_hiprt_SEARCH_DIRS}/include
|
||||
${_hiprt_SEARCH_DIRS}
|
||||
)
|
||||
|
||||
|
@ -36,6 +40,7 @@ if(HIPRT_INCLUDE_DIR)
|
|||
NAMES
|
||||
hiprt${_hiprt_version}_amd_lib_win.bc
|
||||
HINTS
|
||||
${HIPRT_ROOT_DIR}/bin
|
||||
${HIPRT_ROOT_DIR}/dist/bin/Release
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
|
Binary file not shown.
|
@ -2126,6 +2126,10 @@ def km_node_editor(params):
|
|||
# Allow node selection with both for RMB select.
|
||||
if params.select_mouse == 'RIGHTMOUSE':
|
||||
items.extend(_template_node_select(type='LEFTMOUSE', value='PRESS', select_passthrough=True))
|
||||
else:
|
||||
items.extend([
|
||||
op_tool_cycle("builtin.select_box", {"type": 'W', "value": 'PRESS'}),
|
||||
])
|
||||
else:
|
||||
items.extend(_template_node_select(
|
||||
type='RIGHTMOUSE', value=params.select_mouse_value, select_passthrough=True))
|
||||
|
|
|
@ -35,6 +35,29 @@ def geometry_node_group_empty_new():
|
|||
return group
|
||||
|
||||
|
||||
def geometry_node_group_empty_tool_new(context):
|
||||
group = build_default_empty_geometry_node_group(data_("Tool"))
|
||||
group.links.new(group.nodes[data_("Group Input")].outputs[0], group.nodes[data_("Group Output")].inputs[0])
|
||||
group.asset_mark()
|
||||
group.is_tool = True
|
||||
|
||||
ob_type = context.object.type if context.object else 'MESH'
|
||||
if ob_type == 'CURVES':
|
||||
group.is_type_curve = True
|
||||
elif ob_type == 'POINTCLOUD':
|
||||
group.is_type_point_cloud = True
|
||||
else:
|
||||
group.is_type_mesh = True
|
||||
|
||||
mode = context.object.mode if context.object else 'EDIT'
|
||||
if mode in {'SCULPT', 'SCULPT_CURVES'}:
|
||||
group.is_mode_sculpt = True
|
||||
else:
|
||||
group.is_mode_edit = True
|
||||
|
||||
return group
|
||||
|
||||
|
||||
def geometry_modifier_poll(context):
|
||||
ob = context.object
|
||||
|
||||
|
@ -276,9 +299,7 @@ class NewGeometryNodeGroupTool(Operator):
|
|||
return space and space.type == 'NODE_EDITOR' and space.geometry_nodes_type == 'TOOL'
|
||||
|
||||
def execute(self, context):
|
||||
group = geometry_node_group_empty_new()
|
||||
group.asset_mark()
|
||||
group.is_tool = True
|
||||
group = geometry_node_group_empty_tool_new(context)
|
||||
context.space_data.node_tree = group
|
||||
return {'FINISHED'}
|
||||
|
||||
|
|
|
@ -96,16 +96,10 @@ class DATA_UL_bone_collections(UIList):
|
|||
class DATA_PT_bone_collections(ArmatureButtonsPanel, Panel):
|
||||
bl_label = "Bone Collections"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
return (ob and ob.type == 'ARMATURE' and ob.pose)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
ob = context.object
|
||||
arm = ob.data
|
||||
arm = context.armature
|
||||
active_bcoll = arm.collections.active
|
||||
|
||||
row = layout.row()
|
||||
|
@ -243,6 +237,17 @@ class DATA_PT_custom_props_arm(ArmatureButtonsPanel, PropertyPanel, Panel):
|
|||
_property_type = bpy.types.Armature
|
||||
|
||||
|
||||
class DATA_PT_custom_props_bcoll(ArmatureButtonsPanel, PropertyPanel, Panel):
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
|
||||
_context_path = "armature.collections.active"
|
||||
_property_type = bpy.types.BoneCollection
|
||||
bl_parent_id = "DATA_PT_bone_collections"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.armature and context.armature.collections.active
|
||||
|
||||
|
||||
classes = (
|
||||
DATA_PT_context_arm,
|
||||
DATA_PT_skeleton,
|
||||
|
@ -253,6 +258,7 @@ classes = (
|
|||
DATA_PT_display,
|
||||
DATA_PT_iksolver_itasc,
|
||||
DATA_PT_custom_props_arm,
|
||||
DATA_PT_custom_props_bcoll,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
|
|
|
@ -29,6 +29,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
|||
|
||||
class OBJECT_MT_modifier_add(Menu):
|
||||
bl_label = "Add Modifier"
|
||||
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
@ -226,6 +227,7 @@ class AddModifierMenu(Operator):
|
|||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
# NOTE: This operator only exists to add a poll to the add modifier shortcut in the property editor.
|
||||
space = context.space_data
|
||||
return space and space.type == 'PROPERTIES' and space.context == "MODIFIER"
|
||||
|
||||
|
|
|
@ -225,6 +225,7 @@ class NODE_MT_add(bpy.types.Menu):
|
|||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_label = "Add"
|
||||
bl_translation_context = i18n_contexts.operator_default
|
||||
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
||||
|
||||
def draw(self, context):
|
||||
import nodeitems_utils
|
||||
|
@ -234,27 +235,14 @@ class NODE_MT_add(bpy.types.Menu):
|
|||
|
||||
snode = context.space_data
|
||||
if snode.tree_type == 'GeometryNodeTree':
|
||||
props = layout.operator("node.add_search", text="Search...", icon='VIEWZOOM')
|
||||
layout.separator()
|
||||
layout.menu_contents("NODE_MT_geometry_node_add_all")
|
||||
elif snode.tree_type == 'CompositorNodeTree':
|
||||
props = layout.operator("node.add_search", text="Search...", icon='VIEWZOOM')
|
||||
layout.separator()
|
||||
layout.menu_contents("NODE_MT_compositor_node_add_all")
|
||||
elif snode.tree_type == 'ShaderNodeTree':
|
||||
props = layout.operator("node.add_search", text="Search...", icon='VIEWZOOM')
|
||||
layout.separator()
|
||||
layout.menu_contents("NODE_MT_shader_node_add_all")
|
||||
elif snode.tree_type == 'TextureNodeTree':
|
||||
props = layout.operator("node.add_search", text="Search...", icon='VIEWZOOM')
|
||||
layout.separator()
|
||||
layout.menu_contents("NODE_MT_texture_node_add_all")
|
||||
elif nodeitems_utils.has_node_categories(context):
|
||||
props = layout.operator("node.add_search", text="Search...", icon='VIEWZOOM')
|
||||
props.use_transform = True
|
||||
|
||||
layout.separator()
|
||||
|
||||
# Actual node sub-menus are defined by draw functions from node categories.
|
||||
nodeitems_utils.draw_node_categories_menu(self, context)
|
||||
|
||||
|
|
|
@ -966,15 +966,9 @@ class SEQUENCER_MT_strip(Menu):
|
|||
if has_sequencer:
|
||||
if strip:
|
||||
strip_type = strip.type
|
||||
|
||||
if strip_type != 'SOUND':
|
||||
layout.separator()
|
||||
layout.operator_menu_enum("sequencer.strip_video_modifier_add", "type", text="Add Modifier")
|
||||
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
|
||||
else:
|
||||
layout.separator()
|
||||
layout.operator_menu_enum("sequencer.strip_sound_modifier_add", "type", text="Add Modifier")
|
||||
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
|
||||
layout.separator()
|
||||
layout.operator_menu_enum("sequencer.strip_modifier_add", "type", text="Add Modifier")
|
||||
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
|
||||
|
||||
if strip_type in {
|
||||
'CROSS', 'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
|
||||
|
@ -1112,18 +1106,16 @@ class SEQUENCER_MT_context_menu(Menu):
|
|||
strip_type = strip.type
|
||||
selected_sequences_count = selected_sequences_len(context)
|
||||
|
||||
layout.separator()
|
||||
layout.operator_menu_enum("sequencer.strip_modifier_add", "type", text="Add Modifier")
|
||||
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
|
||||
|
||||
if strip_type != 'SOUND':
|
||||
layout.separator()
|
||||
layout.operator_menu_enum("sequencer.strip_video_modifier_add", "type", text="Add Modifier")
|
||||
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
|
||||
if selected_sequences_count >= 2:
|
||||
layout.separator()
|
||||
col = layout.column()
|
||||
col.menu("SEQUENCER_MT_add_transitions", text="Add Transition")
|
||||
else:
|
||||
layout.separator()
|
||||
layout.operator_menu_enum("sequencer.strip_sound_modifier_add", "type", text="Add Modifier")
|
||||
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
|
||||
if selected_sequences_count >= 2:
|
||||
layout.separator()
|
||||
layout.operator("sequencer.crossfade_sounds", text="Crossfade Sounds")
|
||||
|
|
|
@ -2448,6 +2448,7 @@ class VIEW3D_MT_grease_pencil_add(Menu):
|
|||
class VIEW3D_MT_add(Menu):
|
||||
bl_label = "Add"
|
||||
bl_translation_context = i18n_contexts.operator_default
|
||||
bl_options = {'SEARCH_ON_KEY_PRESS'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
|
|
@ -257,6 +257,15 @@ inline int2 face_find_adjecent_verts(const IndexRange face,
|
|||
corner_verts[face_corner_next(face, corner)]};
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of triangles needed to tessellate a face with \a face_size corners.
|
||||
*/
|
||||
inline int face_triangles_num(const int face_size)
|
||||
{
|
||||
BLI_assert(face_size > 2);
|
||||
return face_size - 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the edge's vertex that is not the \a vert.
|
||||
* If neither edge vertex is equal to \a v, returns -1.
|
||||
|
|
|
@ -29,6 +29,9 @@ void BKE_previewimg_freefunc(void *link);
|
|||
*/
|
||||
void BKE_previewimg_free(PreviewImage **prv);
|
||||
|
||||
/** Must be called after reading a preview image from file. */
|
||||
void BKE_previewimg_runtime_data_clear(PreviewImage *prv);
|
||||
|
||||
/**
|
||||
* Clear the preview image or icon, but does not free it.
|
||||
*/
|
||||
|
|
|
@ -405,6 +405,10 @@ enum class MenuTypeFlag {
|
|||
* dependent, menu search has to scan it in different contexts.
|
||||
*/
|
||||
ContextDependent = (1 << 0),
|
||||
/**
|
||||
* Automatically start searching in the menu when pressing a key.
|
||||
*/
|
||||
SearchOnKeyPress = (1 << 1),
|
||||
};
|
||||
ENUM_OPERATORS(MenuTypeFlag, MenuTypeFlag::ContextDependent)
|
||||
|
||||
|
|
|
@ -1104,7 +1104,7 @@ static BitVector<> looptri_no_hidden_map_get(const blender::OffsetIndices<int> f
|
|||
int looptri_no_hidden_len = 0;
|
||||
int looptri_index = 0;
|
||||
for (const int64_t i : faces.index_range()) {
|
||||
const int triangles_num = ME_FACE_TRI_TOT(faces[i].size());
|
||||
const int triangles_num = blender::bke::mesh::face_triangles_num(faces[i].size());
|
||||
if (hide_poly[i]) {
|
||||
looptri_index += triangles_num;
|
||||
}
|
||||
|
|
|
@ -273,6 +273,19 @@ static size_t id_delete(Main *bmain,
|
|||
* code has some specific handling of 'no main' IDs that would be a problem in that
|
||||
* case). */
|
||||
id->tag |= tag;
|
||||
|
||||
/* Forcefully also delete shapekeys of the deleted ID if any, 'orphaned' shapekeys are
|
||||
* not allowed in Blender and will cause lots of problem in modern code (liboverrides,
|
||||
* warning on write & read, etc.). */
|
||||
Key *shape_key = BKE_key_from_id(id);
|
||||
if (shape_key && (shape_key->id.tag & tag) == 0) {
|
||||
BLI_remlink(&bmain->shapekeys, &shape_key->id);
|
||||
BKE_main_namemap_remove_name(bmain, &shape_key->id, shape_key->id.name + 2);
|
||||
BLI_addtail(&tagged_deleted_ids, &shape_key->id);
|
||||
BKE_id_remapper_add(id_remapper, &shape_key->id, nullptr);
|
||||
shape_key->id.tag |= tag;
|
||||
}
|
||||
|
||||
keep_looping = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,6 +80,7 @@ static void library_blend_read_data(BlendDataReader * /*reader*/, ID *id)
|
|||
lib->runtime.name_map = nullptr;
|
||||
/* This is runtime data. */
|
||||
lib->parent = nullptr;
|
||||
lib->tag = 0;
|
||||
}
|
||||
|
||||
IDTypeInfo IDType_ID_LI = {
|
||||
|
|
|
@ -286,7 +286,7 @@ void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map,
|
|||
index_step = indices;
|
||||
for (const int64_t i : faces.index_range()) {
|
||||
map[i].indices = index_step;
|
||||
index_step += ME_FACE_TRI_TOT(faces[i].size());
|
||||
index_step += blender::bke::mesh::face_triangles_num(int(faces[i].size()));
|
||||
}
|
||||
|
||||
/* Assign face-tessellation users. */
|
||||
|
|
|
@ -306,7 +306,7 @@ void looptris_calc_face_indices(const OffsetIndices<int> faces, MutableSpan<int>
|
|||
for (const int64_t i : range) {
|
||||
const IndexRange face = faces[i];
|
||||
const int start = poly_to_tri_count(int(i), int(face.start()));
|
||||
const int num = ME_FACE_TRI_TOT(int(face.size()));
|
||||
const int num = face_triangles_num(int(face.size()));
|
||||
looptri_faces.slice(start, num).fill(int(i));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -369,9 +369,43 @@ static void socket_data_foreach_id(LibraryForeachIDData *data, bNodeTreeInterfac
|
|||
|
||||
namespace item_types {
|
||||
|
||||
using UidGeneratorFn = blender::FunctionRef<int()>;
|
||||
|
||||
static void item_copy(bNodeTreeInterfaceItem &dst,
|
||||
const bNodeTreeInterfaceItem &src,
|
||||
const int flag)
|
||||
int flag,
|
||||
UidGeneratorFn generate_uid);
|
||||
|
||||
/**
|
||||
* Copy the source items and give each a new unique identifier.
|
||||
* \param generate_uid: Optional generator function for new item UIDs, copies existing identifiers
|
||||
* if null.
|
||||
*/
|
||||
static void panel_init(bNodeTreeInterfacePanel &panel,
|
||||
const Span<const bNodeTreeInterfaceItem *> items_src,
|
||||
const int flag,
|
||||
UidGeneratorFn generate_uid)
|
||||
{
|
||||
panel.items_num = items_src.size();
|
||||
panel.items_array = MEM_cnew_array<bNodeTreeInterfaceItem *>(panel.items_num, __func__);
|
||||
|
||||
/* Copy buffers. */
|
||||
for (const int i : items_src.index_range()) {
|
||||
const bNodeTreeInterfaceItem *item_src = items_src[i];
|
||||
panel.items_array[i] = static_cast<bNodeTreeInterfaceItem *>(MEM_dupallocN(item_src));
|
||||
item_types::item_copy(*panel.items_array[i], *item_src, flag, generate_uid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy data from a source item.
|
||||
* \param generate_uid: Optional generator function for new item UIDs, copies existing identifiers
|
||||
* if null.
|
||||
*/
|
||||
static void item_copy(bNodeTreeInterfaceItem &dst,
|
||||
const bNodeTreeInterfaceItem &src,
|
||||
const int flag,
|
||||
UidGeneratorFn generate_uid)
|
||||
{
|
||||
switch (dst.item_type) {
|
||||
case NODE_INTERFACE_SOCKET: {
|
||||
|
@ -385,7 +419,8 @@ static void item_copy(bNodeTreeInterfaceItem &dst,
|
|||
dst_socket.description = BLI_strdup_null(src_socket.description);
|
||||
dst_socket.socket_type = BLI_strdup(src_socket.socket_type);
|
||||
dst_socket.default_attribute_name = BLI_strdup_null(src_socket.default_attribute_name);
|
||||
dst_socket.identifier = BLI_strdup(src_socket.identifier);
|
||||
dst_socket.identifier = generate_uid ? BLI_sprintfN("Socket_%d", generate_uid()) :
|
||||
BLI_strdup(src_socket.identifier);
|
||||
if (src_socket.properties) {
|
||||
dst_socket.properties = IDP_CopyProperty_ex(src_socket.properties, flag);
|
||||
}
|
||||
|
@ -402,24 +437,9 @@ static void item_copy(bNodeTreeInterfaceItem &dst,
|
|||
|
||||
dst_panel.name = BLI_strdup(src_panel.name);
|
||||
dst_panel.description = BLI_strdup_null(src_panel.description);
|
||||
dst_panel.copy_from(src_panel.items(), flag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
dst_panel.identifier = generate_uid ? generate_uid() : src_panel.identifier;
|
||||
|
||||
static void item_set_unique_identifier(const int uid, bNodeTreeInterfaceItem &item)
|
||||
{
|
||||
switch (item.item_type) {
|
||||
case NODE_INTERFACE_SOCKET: {
|
||||
bNodeTreeInterfaceSocket &socket = reinterpret_cast<bNodeTreeInterfaceSocket &>(item);
|
||||
MEM_SAFE_FREE(socket.identifier);
|
||||
socket.identifier = BLI_sprintfN("Socket_%d", uid);
|
||||
break;
|
||||
}
|
||||
case NODE_INTERFACE_PANEL: {
|
||||
bNodeTreeInterfacePanel &panel = reinterpret_cast<bNodeTreeInterfacePanel &>(item);
|
||||
panel.identifier = uid;
|
||||
panel_init(dst_panel, src_panel.items(), flag, generate_uid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -999,20 +1019,6 @@ static bNodeTreeInterfacePanel *make_panel(const int uid,
|
|||
return new_panel;
|
||||
}
|
||||
|
||||
void bNodeTreeInterfacePanel::copy_from(
|
||||
const blender::Span<const bNodeTreeInterfaceItem *> items_src, int flag)
|
||||
{
|
||||
items_num = items_src.size();
|
||||
items_array = MEM_cnew_array<bNodeTreeInterfaceItem *>(items_num, __func__);
|
||||
|
||||
/* Copy buffers. */
|
||||
for (const int i : items_src.index_range()) {
|
||||
const bNodeTreeInterfaceItem *item_src = items_src[i];
|
||||
items_array[i] = static_cast<bNodeTreeInterfaceItem *>(MEM_dupallocN(item_src));
|
||||
item_types::item_copy(*items_array[i], *item_src, flag);
|
||||
}
|
||||
}
|
||||
|
||||
void bNodeTreeInterface::init_data()
|
||||
{
|
||||
/* Root panel is allowed to contain child panels. */
|
||||
|
@ -1021,7 +1027,7 @@ void bNodeTreeInterface::init_data()
|
|||
|
||||
void bNodeTreeInterface::copy_data(const bNodeTreeInterface &src, int flag)
|
||||
{
|
||||
this->root_panel.copy_from(src.root_panel.items(), flag);
|
||||
item_types::panel_init(this->root_panel, src.root_panel.items(), flag, nullptr);
|
||||
this->active_index = src.active_index;
|
||||
}
|
||||
|
||||
|
@ -1188,8 +1194,7 @@ bNodeTreeInterfaceItem *bNodeTreeInterface::add_item_copy(const bNodeTreeInterfa
|
|||
}
|
||||
|
||||
bNodeTreeInterfaceItem *citem = static_cast<bNodeTreeInterfaceItem *>(MEM_dupallocN(&item));
|
||||
item_types::item_copy(*citem, item, 0);
|
||||
item_types::item_set_unique_identifier(next_uid++, *citem);
|
||||
item_types::item_copy(*citem, item, 0, [&]() { return this->next_uid++; });
|
||||
parent->add_item(*citem);
|
||||
|
||||
return citem;
|
||||
|
@ -1213,8 +1218,7 @@ bNodeTreeInterfaceItem *bNodeTreeInterface::insert_item_copy(const bNodeTreeInte
|
|||
}
|
||||
|
||||
bNodeTreeInterfaceItem *citem = static_cast<bNodeTreeInterfaceItem *>(MEM_dupallocN(&item));
|
||||
item_types::item_copy(*citem, item, 0);
|
||||
item_types::item_set_unique_identifier(next_uid++, *citem);
|
||||
item_types::item_copy(*citem, item, 0, [&]() { return this->next_uid++; });
|
||||
parent->insert_item(*citem, position);
|
||||
|
||||
return citem;
|
||||
|
|
|
@ -148,6 +148,15 @@ static void BKE_previewimg_free(PreviewImageDeferred **prv)
|
|||
*prv = nullptr;
|
||||
}
|
||||
|
||||
void BKE_previewimg_runtime_data_clear(PreviewImage *prv)
|
||||
{
|
||||
prv->tag = 0;
|
||||
prv->icon_id = 0;
|
||||
for (int i = 0; i < NUM_ICON_SIZES; i++) {
|
||||
prv->gputexture[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_previewimg_clear_single(PreviewImage *prv, enum eIconSizes size)
|
||||
{
|
||||
MEM_SAFE_FREE(prv->rect[size]);
|
||||
|
@ -508,7 +517,6 @@ void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv)
|
|||
if (prv->rect[i]) {
|
||||
BLO_read_data_address(reader, &prv->rect[i]);
|
||||
}
|
||||
prv->gputexture[i] = nullptr;
|
||||
|
||||
/* PRV_RENDERING is a runtime only flag currently, but don't mess with it on undo! It gets
|
||||
* special handling in #memfile_undosys_restart_unfinished_id_previews() then. */
|
||||
|
@ -516,6 +524,5 @@ void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv)
|
|||
prv->flag[i] &= ~PRV_RENDERING;
|
||||
}
|
||||
}
|
||||
prv->icon_id = 0;
|
||||
prv->tag = 0;
|
||||
BKE_previewimg_runtime_data_clear(prv);
|
||||
}
|
||||
|
|
|
@ -133,6 +133,8 @@ MINLINE void add_v4_v4v4(float r[4], const float a[4], const float b[4]);
|
|||
|
||||
MINLINE void add_v3fl_v3fl_v3i(float r[3], const float a[3], const int b[3]);
|
||||
|
||||
MINLINE void add_v3_uchar_clamped(uchar r[3], int i);
|
||||
|
||||
MINLINE void sub_v2_v2(float r[2], const float a[2]);
|
||||
MINLINE void sub_v2_v2_db(double r[2], const double a[2]);
|
||||
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2]);
|
||||
|
|
|
@ -89,9 +89,9 @@ template<typename T> class OffsetIndices {
|
|||
return OffsetIndices(offsets_.slice(range.start(), range.one_after_last()));
|
||||
}
|
||||
|
||||
const T *data() const
|
||||
Span<T> data() const
|
||||
{
|
||||
return offsets_.data();
|
||||
return offsets_;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -458,6 +458,13 @@ MINLINE void add_v4_v4v4(float r[4], const float a[4], const float b[4])
|
|||
r[3] = a[3] + b[3];
|
||||
}
|
||||
|
||||
MINLINE void add_v3_uchar_clamped(uchar r[3], int i)
|
||||
{
|
||||
r[0] = (uchar)clamp_i(r[0] + i, 0, 255);
|
||||
r[1] = (uchar)clamp_i(r[1] + i, 0, 255);
|
||||
r[2] = (uchar)clamp_i(r[2] + i, 0, 255);
|
||||
}
|
||||
|
||||
MINLINE void sub_v2_v2(float r[2], const float a[2])
|
||||
{
|
||||
r[0] -= a[0];
|
||||
|
|
|
@ -272,6 +272,7 @@ PreviewImage *BLO_blendhandle_get_preview_for_id(BlendHandle *bh,
|
|||
if (preview_from_file == nullptr) {
|
||||
break;
|
||||
}
|
||||
BKE_previewimg_runtime_data_clear(preview_from_file);
|
||||
|
||||
PreviewImage *result = static_cast<PreviewImage *>(MEM_dupallocN(preview_from_file));
|
||||
bhead = blo_blendhandle_read_preview_rects(fd, bhead, result, preview_from_file);
|
||||
|
@ -334,6 +335,8 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *r_
|
|||
prv = static_cast<PreviewImage *>(BLO_library_read_struct(fd, bhead, "PreviewImage"));
|
||||
|
||||
if (prv) {
|
||||
BKE_previewimg_runtime_data_clear(prv);
|
||||
|
||||
memcpy(new_prv, prv, sizeof(PreviewImage));
|
||||
bhead = blo_blendhandle_read_preview_rects(fd, bhead, new_prv, prv);
|
||||
MEM_freeN(prv);
|
||||
|
|
|
@ -88,6 +88,12 @@ static void version_bonegroup_migrate_color(Main *bmain)
|
|||
bArmature *arm = reinterpret_cast<bArmature *>(ob->data);
|
||||
BLI_assert_msg(GS(arm->id.name) == ID_AR,
|
||||
"Expected ARMATURE object to have an Armature as data");
|
||||
|
||||
/* There is no guarantee that the current state of poses is in sync with the Armature data.
|
||||
*
|
||||
* NOTE: No need to handle user refcounting in readfile code. */
|
||||
BKE_pose_ensure(bmain, ob, arm, false);
|
||||
|
||||
PoseSet &pose_set = armature_poses.lookup_or_add_default(arm);
|
||||
pose_set.add(ob->pose);
|
||||
}
|
||||
|
|
|
@ -390,7 +390,7 @@ BLI_INLINE void extract_task_range_run_iter(const MeshRenderData &mr,
|
|||
stop = mr.tri_len;
|
||||
break;
|
||||
case MR_ITER_POLY:
|
||||
range_data.elems = is_mesh ? mr.faces.data() : (void *)mr.bm->ftable;
|
||||
range_data.elems = is_mesh ? mr.faces.data().data() : (void *)mr.bm->ftable;
|
||||
func = is_mesh ? extract_range_iter_face_mesh : extract_range_iter_face_bm;
|
||||
stop = mr.face_len;
|
||||
break;
|
||||
|
|
|
@ -204,14 +204,14 @@ static void accumululate_material_counts_mesh(
|
|||
for (const int i : range) {
|
||||
if (!mr.hide_poly[i]) {
|
||||
const int mat = std::clamp(material_indices[i], 0, last_index);
|
||||
tri_counts[mat] += ME_FACE_TRI_TOT(faces[i].size());
|
||||
tri_counts[mat] += bke::mesh::face_triangles_num(faces[i].size());
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const int i : range) {
|
||||
const int mat = std::clamp(material_indices[i], 0, last_index);
|
||||
tri_counts[mat] += ME_FACE_TRI_TOT(faces[i].size());
|
||||
tri_counts[mat] += bke::mesh::face_triangles_num(faces[i].size());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -175,6 +175,8 @@ enum {
|
|||
UI_BLOCK_SEARCH_ONLY = 1 << 25,
|
||||
/** Hack for quick setup (splash screen) to draw text centered. */
|
||||
UI_BLOCK_QUICK_SETUP = 1 << 26,
|
||||
/** Don't accelerator keys for the items in the block. */
|
||||
UI_BLOCK_NO_ACCELERATOR_KEYS = 1 << 27,
|
||||
};
|
||||
|
||||
/** #uiPopupBlockHandle.menuretval */
|
||||
|
@ -247,6 +249,15 @@ enum {
|
|||
UI_BUT_OVERRIDDEN = 1u << 31u,
|
||||
};
|
||||
|
||||
enum {
|
||||
/**
|
||||
* This is used when `UI_BUT_ACTIVATE_ON_INIT` is used, which is used to activate e.g. a search
|
||||
* box as soon as a popup opens. Usually, the text in the search box is selected by default.
|
||||
* However, sometimes this behavior is not desired, so it can be disabled with this flag.
|
||||
*/
|
||||
UI_BUT2_ACTIVATE_ON_INIT_NO_SELECT = 1 << 0,
|
||||
};
|
||||
|
||||
/** #uiBut.dragflag */
|
||||
enum {
|
||||
/** By default only the left part of a button triggers dragging. A questionable design to make
|
||||
|
@ -887,6 +898,7 @@ bool UI_but_active_drop_color(bContext *C);
|
|||
void UI_but_flag_enable(uiBut *but, int flag);
|
||||
void UI_but_flag_disable(uiBut *but, int flag);
|
||||
bool UI_but_flag_is_set(uiBut *but, int flag);
|
||||
void UI_but_flag2_enable(uiBut *but, int flag);
|
||||
|
||||
void UI_but_drawflag_enable(uiBut *but, int flag);
|
||||
void UI_but_drawflag_disable(uiBut *but, int flag);
|
||||
|
@ -2404,7 +2416,7 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C);
|
|||
void UI_but_func_operator_search(uiBut *but);
|
||||
void uiTemplateOperatorSearch(uiLayout *layout);
|
||||
|
||||
void UI_but_func_menu_search(uiBut *but);
|
||||
void UI_but_func_menu_search(uiBut *but, const char *single_menu_idname = nullptr);
|
||||
void uiTemplateMenuSearch(uiLayout *layout);
|
||||
|
||||
/**
|
||||
|
|
|
@ -2001,7 +2001,9 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x
|
|||
UI_block_layout_resolve(block, nullptr, nullptr);
|
||||
}
|
||||
ui_block_align_calc(block, CTX_wm_region(C));
|
||||
if ((block->flag & UI_BLOCK_LOOP) && (block->flag & UI_BLOCK_NUMSELECT)) {
|
||||
if ((block->flag & UI_BLOCK_LOOP) && (block->flag & UI_BLOCK_NUMSELECT) &&
|
||||
(block->flag & UI_BLOCK_NO_ACCELERATOR_KEYS) == 0)
|
||||
{
|
||||
ui_menu_block_set_keyaccels(block); /* could use a different flag to check */
|
||||
}
|
||||
|
||||
|
@ -4467,9 +4469,8 @@ static void ui_def_but_rna__menu(bContext * /*C*/, uiLayout *layout, void *but_p
|
|||
-1,
|
||||
item->description);
|
||||
}
|
||||
item_but->flag |= UI_BUT_LIST_ITEM;
|
||||
if (item->value == current_value) {
|
||||
item_but->flag |= UI_BUT_ACTIVE_DEFAULT;
|
||||
item_but->flag |= UI_SELECT_DRAW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5848,6 +5849,11 @@ void UI_but_flag_enable(uiBut *but, int flag)
|
|||
but->flag |= flag;
|
||||
}
|
||||
|
||||
void UI_but_flag2_enable(uiBut *but, int flag)
|
||||
{
|
||||
but->flag2 |= flag;
|
||||
}
|
||||
|
||||
void UI_but_flag_disable(uiBut *but, int flag)
|
||||
{
|
||||
but->flag &= ~flag;
|
||||
|
|
|
@ -3480,7 +3480,12 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
|
|||
/* set cursor pos to the end of the text */
|
||||
but->editstr = data->str;
|
||||
but->pos = len;
|
||||
but->selsta = 0;
|
||||
if (bool(but->flag2 & UI_BUT2_ACTIVATE_ON_INIT_NO_SELECT)) {
|
||||
but->selsta = len;
|
||||
}
|
||||
else {
|
||||
but->selsta = 0;
|
||||
}
|
||||
but->selend = len;
|
||||
|
||||
/* Initialize undo history tracking. */
|
||||
|
@ -4316,6 +4321,9 @@ static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *dat
|
|||
}
|
||||
else if (menufunc) {
|
||||
data->menu = ui_popup_menu_create(C, data->region, but, menufunc, arg);
|
||||
if (MenuType *mt = UI_but_menutype_get(but)) {
|
||||
STRNCPY(data->menu->menu_idname, mt->idname);
|
||||
}
|
||||
if (but->block->handle) {
|
||||
data->menu->popup = but->block->handle->popup;
|
||||
}
|
||||
|
@ -9107,6 +9115,13 @@ void ui_but_activate_event(bContext *C, ARegion *region, uiBut *but)
|
|||
|
||||
void ui_but_activate_over(bContext *C, ARegion *region, uiBut *but)
|
||||
{
|
||||
/* If there is an active button in the currently active region,
|
||||
* then add UI_SELECT_DRAW to the to-be-activated button. */
|
||||
ARegion *active_region = CTX_wm_region(C);
|
||||
if (active_region && ui_region_find_active_but(active_region)) {
|
||||
but->flag |= UI_SELECT_DRAW;
|
||||
}
|
||||
|
||||
button_activate_init(C, region, but, BUTTON_ACTIVATE_OVER);
|
||||
}
|
||||
|
||||
|
@ -10269,6 +10284,41 @@ float ui_block_calc_pie_segment(uiBlock *block, const float event_xy[2])
|
|||
return len;
|
||||
}
|
||||
|
||||
static int ui_handle_menu_letter_press(
|
||||
bContext *C, ARegion *region, uiPopupBlockHandle *menu, const wmEvent *event, uiBlock *block)
|
||||
{
|
||||
/* Start menu search on key press if enabled. */
|
||||
if (menu->menu_idname[0]) {
|
||||
MenuType *mt = WM_menutype_find(menu->menu_idname, false);
|
||||
if (bool(mt->flag & MenuTypeFlag::SearchOnKeyPress)) {
|
||||
uiAfterFunc *after = ui_afterfunc_new();
|
||||
wmOperatorType *ot = WM_operatortype_find("WM_OT_search_single_menu", false);
|
||||
after->optype = ot;
|
||||
after->opcontext = WM_OP_INVOKE_DEFAULT;
|
||||
after->opptr = MEM_cnew<PointerRNA>(__func__);
|
||||
WM_operator_properties_create_ptr(after->opptr, ot);
|
||||
RNA_string_set(after->opptr, "menu_idname", menu->menu_idname);
|
||||
RNA_string_set(after->opptr, "initial_query", event->utf8_buf);
|
||||
menu->menuretval = UI_RETURN_OK;
|
||||
return WM_UI_HANDLER_BREAK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle accelerator keys that allow "pressing" a menu entry by pressing a single key. */
|
||||
LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
|
||||
if (!(but->flag & UI_BUT_DISABLED) && but->menu_key == event->type) {
|
||||
if (but->type == UI_BTYPE_BUT) {
|
||||
UI_but_execute(C, region, but);
|
||||
}
|
||||
else {
|
||||
ui_handle_button_activate_by_type(C, region, but);
|
||||
}
|
||||
return WM_UI_HANDLER_BREAK;
|
||||
}
|
||||
}
|
||||
return WM_UI_HANDLER_CONTINUE;
|
||||
}
|
||||
|
||||
static int ui_handle_menu_event(bContext *C,
|
||||
const wmEvent *event,
|
||||
uiPopupBlockHandle *menu,
|
||||
|
@ -10709,20 +10759,7 @@ static int ui_handle_menu_event(bContext *C,
|
|||
menu, but, level, is_parent_menu, retval)) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (but = static_cast<uiBut *>(block->buttons.first); but; but = but->next) {
|
||||
if (!(but->flag & UI_BUT_DISABLED) && but->menu_key == event->type) {
|
||||
if (but->type == UI_BTYPE_BUT) {
|
||||
UI_but_execute(C, region, but);
|
||||
}
|
||||
else {
|
||||
ui_handle_button_activate_by_type(C, region, but);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
retval = WM_UI_HANDLER_BREAK;
|
||||
retval = ui_handle_menu_letter_press(C, region, menu, event, block);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -151,6 +151,7 @@ struct uiBut {
|
|||
/** Pointer back to the layout item holding this button. */
|
||||
uiLayout *layout = nullptr;
|
||||
int flag = 0;
|
||||
int flag2 = 0;
|
||||
int drawflag = 0;
|
||||
eButType type = eButType(0);
|
||||
eButPointerType pointype = UI_BUT_POIN_NONE;
|
||||
|
@ -848,6 +849,8 @@ struct uiPopupBlockHandle {
|
|||
bool is_grab;
|
||||
int grab_xy_prev[2];
|
||||
/* #endif */
|
||||
|
||||
char menu_idname[64];
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -5918,9 +5918,12 @@ void UI_menutype_draw(bContext *C, MenuType *mt, uiLayout *layout)
|
|||
printf("%s: opening menu \"%s\"\n", __func__, mt->idname);
|
||||
}
|
||||
|
||||
uiBlock *block = uiLayoutGetBlock(layout);
|
||||
if (bool(mt->flag & MenuTypeFlag::SearchOnKeyPress)) {
|
||||
UI_block_flag_enable(block, UI_BLOCK_NO_ACCELERATOR_KEYS);
|
||||
}
|
||||
if (mt->listener) {
|
||||
/* Forward the menu type listener to the block we're drawing in. */
|
||||
uiBlock *block = uiLayoutGetBlock(layout);
|
||||
uiBlockDynamicListener *listener = static_cast<uiBlockDynamicListener *>(
|
||||
MEM_mallocN(sizeof(*listener), __func__));
|
||||
listener->listener_func = mt->listener;
|
||||
|
|
|
@ -397,6 +397,12 @@ static uiPopupBlockHandle *ui_popup_menu_create(
|
|||
if (but) {
|
||||
pup->slideout = ui_block_is_menu(but->block);
|
||||
pup->but = but;
|
||||
|
||||
if (MenuType *mt = UI_but_menutype_get(but)) {
|
||||
if (bool(mt->flag & MenuTypeFlag::SearchOnKeyPress)) {
|
||||
ED_workspace_status_text(C, TIP_("Type to search..."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!but) {
|
||||
|
@ -608,7 +614,12 @@ static void ui_popup_menu_create_from_menutype(bContext *C,
|
|||
ui_item_menutype_func(C, layout, mt);
|
||||
});
|
||||
|
||||
STRNCPY(handle->menu_idname, mt->idname);
|
||||
handle->can_refresh = true;
|
||||
|
||||
if (bool(mt->flag & MenuTypeFlag::SearchOnKeyPress)) {
|
||||
ED_workspace_status_text(C, TIP_("Type to search..."));
|
||||
}
|
||||
}
|
||||
|
||||
int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports)
|
||||
|
|
|
@ -575,6 +575,11 @@ uiBlock *ui_popup_block_refresh(bContext *C,
|
|||
block = handle_create_func(C, handle, arg);
|
||||
}
|
||||
|
||||
/* Don't create accelerator keys if the parent menu does not have them. */
|
||||
if (but && but->block->flag & UI_BLOCK_NO_ACCELERATOR_KEYS) {
|
||||
block->flag |= UI_BLOCK_NO_ACCELERATOR_KEYS;
|
||||
}
|
||||
|
||||
/* callbacks _must_ leave this for us, otherwise we can't call UI_block_update_from_old */
|
||||
BLI_assert(!block->endblock);
|
||||
|
||||
|
@ -815,6 +820,10 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C,
|
|||
|
||||
void ui_popup_block_free(bContext *C, uiPopupBlockHandle *handle)
|
||||
{
|
||||
/* This disables the status bar text that is set when opening a menu that supports search (see
|
||||
* #MenuTypeFlag::SearchOnKeyPress). */
|
||||
ED_workspace_status_text(C, nullptr);
|
||||
|
||||
/* If this popup is created from a popover which does NOT have keep-open flag set,
|
||||
* then close the popover too. We could extend this to other popup types too. */
|
||||
ARegion *region = handle->popup_create_vars.butregion;
|
||||
|
|
|
@ -428,8 +428,12 @@ static void menu_items_from_all_operators(bContext *C, MenuSearch_Data *data)
|
|||
* - Look up predefined editor-menus.
|
||||
* - Look up key-map items which call menus.
|
||||
*/
|
||||
static MenuSearch_Data *menu_items_from_ui_create(
|
||||
bContext *C, wmWindow *win, ScrArea *area_init, ARegion *region_init, bool include_all_areas)
|
||||
static MenuSearch_Data *menu_items_from_ui_create(bContext *C,
|
||||
wmWindow *win,
|
||||
ScrArea *area_init,
|
||||
ARegion *region_init,
|
||||
bool include_all_areas,
|
||||
const char *single_menu_idname)
|
||||
{
|
||||
MemArena *memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
|
||||
blender::Map<MenuType *, const char *> menu_display_name_map;
|
||||
|
@ -591,11 +595,18 @@ static MenuSearch_Data *menu_items_from_ui_create(
|
|||
region = region_init;
|
||||
}
|
||||
|
||||
/* Populate menus from the editors,
|
||||
* note that we could create a fake header, draw the header and extract the menus
|
||||
* from the buttons, however this is quite involved and can be avoided as by convention
|
||||
* each space-type has a single root-menu that headers use. */
|
||||
{
|
||||
if (single_menu_idname) {
|
||||
if (MenuType *mt = WM_menutype_find(single_menu_idname, false)) {
|
||||
if (menu_tagged.add(mt)) {
|
||||
menu_stack.push({mt});
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Populate menus from the editors,
|
||||
* note that we could create a fake header, draw the header and extract the menus
|
||||
* from the buttons, however this is quite involved and can be avoided as by convention
|
||||
* each space-type has a single root-menu that headers use. */
|
||||
const char *idname_array[2] = {nullptr};
|
||||
int idname_array_len = 0;
|
||||
|
||||
|
@ -798,12 +809,14 @@ static MenuSearch_Data *menu_items_from_ui_create(
|
|||
}
|
||||
UI_block_free(nullptr, block);
|
||||
|
||||
/* Add key-map items as a second pass,
|
||||
* so all menus are accessed from the header & top-bar before key shortcuts are expanded. */
|
||||
if (menu_stack.is_empty() && (has_keymap_menu_items == false)) {
|
||||
has_keymap_menu_items = true;
|
||||
menu_types_add_from_keymap_items(
|
||||
C, win, area, region, menu_stack, menu_to_kmi, menu_tagged);
|
||||
if (single_menu_idname == nullptr) {
|
||||
/* Add key-map items as a second pass, so all menus are accessed from the header & top-bar
|
||||
* before key shortcuts are expanded. */
|
||||
if (menu_stack.is_empty() && (has_keymap_menu_items == false)) {
|
||||
has_keymap_menu_items = true;
|
||||
menu_types_add_from_keymap_items(
|
||||
C, win, area, region, menu_stack, menu_to_kmi, menu_tagged);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -887,7 +900,7 @@ static MenuSearch_Data *menu_items_from_ui_create(
|
|||
* - Many operators need options to be set to give useful results, see: #74157.
|
||||
* - User who really prefer to list all operators can use #WM_OT_search_operator.
|
||||
*/
|
||||
if (U.flag & USER_DEVELOPER_UI) {
|
||||
if ((U.flag & USER_DEVELOPER_UI) && single_menu_idname == nullptr) {
|
||||
menu_items_from_all_operators(C, data);
|
||||
}
|
||||
|
||||
|
@ -1112,15 +1125,17 @@ static ARegion *ui_search_menu_create_tooltip(
|
|||
/** \name Menu Search Template Public API
|
||||
* \{ */
|
||||
|
||||
void UI_but_func_menu_search(uiBut *but)
|
||||
void UI_but_func_menu_search(uiBut *but, const char *single_menu_idname)
|
||||
{
|
||||
bContext *C = (bContext *)but->block->evil_C;
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
/* When run from top-bar scan all areas in the current window. */
|
||||
const bool include_all_areas = (area && (area->spacetype == SPACE_TOPBAR));
|
||||
MenuSearch_Data *data = menu_items_from_ui_create(C, win, area, region, include_all_areas);
|
||||
const bool include_all_areas = (area && (area->spacetype == SPACE_TOPBAR)) &&
|
||||
!single_menu_idname;
|
||||
MenuSearch_Data *data = menu_items_from_ui_create(
|
||||
C, win, area, region, include_all_areas, single_menu_idname);
|
||||
UI_but_func_search_set(but,
|
||||
/* Generic callback. */
|
||||
ui_searchbox_create_menu,
|
||||
|
|
|
@ -6397,6 +6397,21 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
|
|||
uiBlock *block = uiLayoutGetBlock(ui_abs);
|
||||
eUIEmbossType previous_emboss = UI_block_emboss_get(block);
|
||||
|
||||
uchar report_icon_color[4];
|
||||
uchar report_text_color[4];
|
||||
|
||||
UI_GetThemeColorType4ubv(
|
||||
UI_icon_colorid_from_report_type(report->type), SPACE_INFO, report_icon_color);
|
||||
UI_GetThemeColorType4ubv(
|
||||
UI_text_colorid_from_report_type(report->type), SPACE_INFO, report_text_color);
|
||||
report_text_color[3] = 255; /* This theme color is RGB only, so have to set alpha here. */
|
||||
|
||||
if (rti->flash_progress <= 1.0) {
|
||||
/* Flash report briefly according to progress through fade-out duration. */
|
||||
const int brighten_amount = int(32 * (1.0f - rti->flash_progress));
|
||||
add_v3_uchar_clamped(report_icon_color, brighten_amount);
|
||||
}
|
||||
|
||||
UI_fontstyle_set(&style->widgetlabel);
|
||||
int width = BLF_width(style->widgetlabel.uifont_id, report->message, report->len);
|
||||
width = min_ii(int(rti->widthfac * width), width);
|
||||
|
@ -6420,7 +6435,7 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
|
|||
0,
|
||||
"");
|
||||
/* UI_BTYPE_ROUNDBOX's bg color is set in but->col. */
|
||||
UI_GetThemeColorType4ubv(UI_icon_colorid_from_report_type(report->type), SPACE_INFO, but->col);
|
||||
copy_v4_v4_uchar(but->col, report_icon_color);
|
||||
|
||||
/* Background for the rest of the message. */
|
||||
but = uiDefBut(block,
|
||||
|
@ -6437,9 +6452,8 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
|
|||
0,
|
||||
0,
|
||||
"");
|
||||
|
||||
/* Use icon background at low opacity to highlight, but still contrasting with area TH_TEXT. */
|
||||
UI_GetThemeColorType4ubv(UI_icon_colorid_from_report_type(report->type), SPACE_INFO, but->col);
|
||||
copy_v3_v3_uchar(but->col, report_icon_color);
|
||||
but->col[3] = 64;
|
||||
|
||||
UI_block_align_end(block);
|
||||
|
@ -6456,8 +6470,7 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
|
|||
UI_UNIT_X,
|
||||
UI_UNIT_Y,
|
||||
TIP_("Click to open the info editor"));
|
||||
UI_GetThemeColorType4ubv(UI_text_colorid_from_report_type(report->type), SPACE_INFO, but->col);
|
||||
but->col[3] = 255; /* This theme color is RBG only, so have to set alpha here. */
|
||||
copy_v4_v4_uchar(but->col, report_text_color);
|
||||
|
||||
/* The report message. */
|
||||
but = uiDefButO(block,
|
||||
|
|
|
@ -154,13 +154,6 @@ static void color_blend_v4_v4v4(uchar r_col[4],
|
|||
r_col[3] = (faci * col1[3] + facm * col2[3]) / 256;
|
||||
}
|
||||
|
||||
static void color_add_v3_i(uchar cp[3], int tint)
|
||||
{
|
||||
cp[0] = clamp_i(cp[0] + tint, 0, 255);
|
||||
cp[1] = clamp_i(cp[1] + tint, 0, 255);
|
||||
cp[2] = clamp_i(cp[2] + tint, 0, 255);
|
||||
}
|
||||
|
||||
static void color_ensure_contrast_v3(uchar cp[3], const uchar cp_other[3], int contrast)
|
||||
{
|
||||
BLI_assert(contrast > 0);
|
||||
|
@ -169,12 +162,12 @@ static void color_ensure_contrast_v3(uchar cp[3], const uchar cp_other[3], int c
|
|||
const int delta = item_value - inner_value;
|
||||
if (delta >= 0) {
|
||||
if (contrast > delta) {
|
||||
color_add_v3_i(cp, contrast - delta);
|
||||
add_v3_uchar_clamped(cp, contrast - delta);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (contrast > -delta) {
|
||||
color_add_v3_i(cp, -contrast - delta);
|
||||
add_v3_uchar_clamped(cp, -contrast - delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1269,8 +1262,8 @@ static void widgetbase_draw_ex(uiWidgetBase *wtb,
|
|||
outline_col[2] = wcol->outline[2];
|
||||
outline_col[3] = wcol->outline[3];
|
||||
|
||||
/* emboss bottom shadow */
|
||||
if (wtb->draw_emboss) {
|
||||
/* Emboss shadow if enabled, and inner and outline colors are not fully transparent. */
|
||||
if ((wtb->draw_emboss) && (wcol->inner[3] != 0.0f || wcol->outline[3] != 0.0f)) {
|
||||
UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss_col);
|
||||
}
|
||||
}
|
||||
|
@ -2737,10 +2730,8 @@ static void widget_state_menu_item(uiWidgetType *wt,
|
|||
/* Regular disabled. */
|
||||
color_blend_v3_v3(wt->wcol.text, wt->wcol.inner, 0.5f);
|
||||
}
|
||||
else if ((state->but_flag & UI_BUT_LIST_ITEM) &&
|
||||
state->but_flag & (UI_BUT_ACTIVE_DEFAULT | UI_SELECT))
|
||||
{
|
||||
/* Currently-selected list item. */
|
||||
else if (state->but_flag & (UI_BUT_ACTIVE_DEFAULT | UI_SELECT_DRAW)) {
|
||||
/* Currently-selected item. */
|
||||
copy_v4_v4_uchar(wt->wcol.inner, wt->wcol.inner_sel);
|
||||
copy_v4_v4_uchar(wt->wcol.text, wt->wcol.text_sel);
|
||||
}
|
||||
|
|
|
@ -219,6 +219,9 @@ static int modifier_add_asset_exec(bContext *C, wmOperator *op)
|
|||
id_us_plus(&node_group->id);
|
||||
MOD_nodes_update_interface(object, nmd);
|
||||
|
||||
/* By default, don't show the data-block selector since it's not usually necessary for assets. */
|
||||
nmd->flag |= NODES_MODIFIER_HIDE_DATABLOCK_SELECTOR;
|
||||
|
||||
STRNCPY(nmd->modifier.name, DATA_(node_group->id.name + 2));
|
||||
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, object);
|
||||
|
|
|
@ -3027,6 +3027,10 @@ static int drop_geometry_nodes_invoke(bContext *C, wmOperator *op, const wmEvent
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (!RNA_boolean_get(op->ptr, "show_datablock_in_modifier")) {
|
||||
nmd->flag |= NODES_MODIFIER_HIDE_DATABLOCK_SELECTOR;
|
||||
}
|
||||
|
||||
nmd->node_group = node_tree;
|
||||
id_us_plus(&node_tree->id);
|
||||
MOD_nodes_update_interface(ob, nmd);
|
||||
|
@ -3057,6 +3061,11 @@ void OBJECT_OT_drop_geometry_nodes(wmOperatorType *ot)
|
|||
INT32_MIN,
|
||||
INT32_MAX);
|
||||
RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE));
|
||||
RNA_def_boolean(ot->srna,
|
||||
"show_datablock_in_modifier",
|
||||
true,
|
||||
"Show the datablock selector in the modifier",
|
||||
"");
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -1070,12 +1070,9 @@ static void draw_fcurve_curve_keys(
|
|||
|
||||
const int2 bounding_indices = get_bounding_bezt_indices(fcu, v2d->cur.xmin, v2d->cur.xmax);
|
||||
|
||||
/* This happens if there is only 1 frame in the curve or the view is only showing the
|
||||
* extrapolation zone of the curve. */
|
||||
if (bounding_indices[0] == bounding_indices[1]) {
|
||||
BezTriple *bezt = &fcu->bezt[bounding_indices[0]];
|
||||
curve_vertices.append({bezt->vec[1][0], bezt->vec[1][1]});
|
||||
}
|
||||
/* Always add the first point so the extrapolation line doesn't jump. */
|
||||
curve_vertices.append(
|
||||
{fcu->bezt[bounding_indices[0]].vec[1][0], fcu->bezt[bounding_indices[0]].vec[1][1]});
|
||||
|
||||
const blender::float2 pixels_per_unit = calculate_pixels_per_unit(v2d);
|
||||
const int window_width = BLI_rcti_size_x(&v2d->mask);
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include "WM_types.hh"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_define.hh"
|
||||
|
@ -574,17 +573,11 @@ void FILE_OT_find_missing_files(wmOperatorType *ot)
|
|||
#define ERROR_TIMEOUT 10.0f
|
||||
#define FLASH_TIMEOUT 1.0f
|
||||
#define COLLAPSE_TIMEOUT 0.25f
|
||||
#define BRIGHTEN_AMOUNT 0.1f
|
||||
|
||||
static int update_reports_display_invoke(bContext *C, wmOperator * /*op*/, const wmEvent *event)
|
||||
{
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
ReportList *reports = CTX_wm_reports(C);
|
||||
Report *report;
|
||||
ReportTimerInfo *rti;
|
||||
float target_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
float progress = 0.0, flash_progress = 0.0;
|
||||
float timeout = 0.0, flash_timeout = FLASH_TIMEOUT;
|
||||
int send_note = 0;
|
||||
|
||||
/* escape if not our timer */
|
||||
if ((reports->reporttimer == nullptr) || (reports->reporttimer != event->customdata) ||
|
||||
|
@ -594,12 +587,16 @@ static int update_reports_display_invoke(bContext *C, wmOperator * /*op*/, const
|
|||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
rti = (ReportTimerInfo *)reports->reporttimer->customdata;
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
ReportTimerInfo *rti = (ReportTimerInfo *)reports->reporttimer->customdata;
|
||||
const float flash_timeout = FLASH_TIMEOUT;
|
||||
bool send_notifier = false;
|
||||
|
||||
timeout = (report->type & RPT_ERROR_ALL) ? ERROR_TIMEOUT : INFO_TIMEOUT;
|
||||
const float timeout = (report->type & RPT_ERROR_ALL) ? ERROR_TIMEOUT : INFO_TIMEOUT;
|
||||
const float time_duration = float(reports->reporttimer->time_duration);
|
||||
|
||||
/* clear the report display after timeout */
|
||||
if (float(reports->reporttimer->time_duration) > timeout) {
|
||||
if (time_duration > timeout) {
|
||||
WM_event_timer_remove(wm, nullptr, reports->reporttimer);
|
||||
reports->reporttimer = nullptr;
|
||||
|
||||
|
@ -608,41 +605,28 @@ static int update_reports_display_invoke(bContext *C, wmOperator * /*op*/, const
|
|||
return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
|
||||
}
|
||||
|
||||
/* set target color based on report type */
|
||||
UI_GetThemeColorType3fv(UI_icon_colorid_from_report_type(report->type), SPACE_INFO, target_col);
|
||||
target_col[3] = 0.65f;
|
||||
|
||||
if (rti->widthfac == 0.0f) {
|
||||
/* initialize color to a brighter shade of the target color */
|
||||
rti->col[0] = target_col[0] + BRIGHTEN_AMOUNT;
|
||||
rti->col[1] = target_col[1] + BRIGHTEN_AMOUNT;
|
||||
rti->col[2] = target_col[2] + BRIGHTEN_AMOUNT;
|
||||
rti->col[3] = 1.0f;
|
||||
|
||||
CLAMP3(rti->col, 0.0, 1.0);
|
||||
|
||||
rti->widthfac = 1.0f;
|
||||
}
|
||||
|
||||
progress = powf(float(reports->reporttimer->time_duration) / timeout, 2.0f);
|
||||
flash_progress = powf(float(reports->reporttimer->time_duration) / flash_timeout, 2.0);
|
||||
const float progress = powf(time_duration / timeout, 2.0f);
|
||||
const float flash_progress = powf(time_duration / flash_timeout, 2.0);
|
||||
|
||||
/* save us from too many draws */
|
||||
if (flash_progress <= 1.0f) {
|
||||
send_note = 1;
|
||||
|
||||
/* flash report briefly according to progress through fade-out duration */
|
||||
interp_v4_v4v4(rti->col, rti->col, target_col, flash_progress);
|
||||
/* Flash report briefly according to progress through fade-out duration. */
|
||||
send_notifier = true;
|
||||
}
|
||||
rti->flash_progress = flash_progress;
|
||||
|
||||
/* collapse report at end of timeout */
|
||||
if (progress * timeout > timeout - COLLAPSE_TIMEOUT) {
|
||||
rti->widthfac = (progress * timeout - (timeout - COLLAPSE_TIMEOUT)) / COLLAPSE_TIMEOUT;
|
||||
rti->widthfac = 1.0f - rti->widthfac;
|
||||
send_note = 1;
|
||||
send_notifier = true;
|
||||
}
|
||||
|
||||
if (send_note) {
|
||||
if (send_notifier) {
|
||||
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, nullptr);
|
||||
}
|
||||
|
||||
|
|
|
@ -526,7 +526,6 @@ static void node_update_basis_from_declaration(
|
|||
if (!is_parent_collapsed) {
|
||||
locy -= NODE_DY;
|
||||
is_first = false;
|
||||
need_spacer_after_item = true;
|
||||
}
|
||||
|
||||
SET_FLAG_FROM_TEST(
|
||||
|
@ -1758,6 +1757,12 @@ static void node_draw_panels_background(const bNode &node, uiBlock &block)
|
|||
|
||||
const nodes::NodeDeclaration &decl = *node.declaration();
|
||||
const rctf &rct = node.runtime->totr;
|
||||
float color_panel[4];
|
||||
UI_GetThemeColorBlend4f(TH_BACK, TH_NODE, 0.2f, color_panel);
|
||||
|
||||
/* True if the last panel is open, draw bottom gap as background. */
|
||||
bool is_last_panel_visible = false;
|
||||
float last_panel_content_y = 0.0f;
|
||||
|
||||
int panel_i = 0;
|
||||
for (const nodes::ItemDeclarationPtr &item_decl : decl.items) {
|
||||
|
@ -1769,25 +1774,21 @@ static void node_draw_panels_background(const bNode &node, uiBlock &block)
|
|||
}
|
||||
|
||||
const bNodePanelState &state = node.panel_states()[panel_i];
|
||||
const bke::bNodePanelRuntime &runtime = node.runtime->panels[panel_i];
|
||||
|
||||
/* Don't draw hidden or collapsed panels. */
|
||||
if (state.is_collapsed() || state.is_parent_collapsed()) {
|
||||
const bool is_visible = !(state.is_collapsed() || state.is_parent_collapsed());
|
||||
is_last_panel_visible = is_visible;
|
||||
last_panel_content_y = runtime.max_content_y;
|
||||
if (!is_visible) {
|
||||
++panel_i;
|
||||
continue;
|
||||
}
|
||||
const bke::bNodePanelRuntime &runtime = node.runtime->panels[panel_i];
|
||||
|
||||
const rctf content_rect = {
|
||||
rct.xmin,
|
||||
rct.xmax,
|
||||
runtime.min_content_y,
|
||||
runtime.max_content_y,
|
||||
};
|
||||
|
||||
UI_block_emboss_set(&block, UI_EMBOSS_NONE);
|
||||
|
||||
/* Panel background. */
|
||||
float color_panel[4];
|
||||
UI_GetThemeColorBlend4f(TH_BACK, TH_NODE, 0.2f, color_panel);
|
||||
const rctf content_rect = {rct.xmin, rct.xmax, runtime.min_content_y, runtime.max_content_y};
|
||||
UI_draw_roundbox_corner_set(UI_CNR_NONE);
|
||||
UI_draw_roundbox_4fv(&content_rect, true, BASIS_RAD, color_panel);
|
||||
|
||||
|
@ -1795,6 +1796,17 @@ static void node_draw_panels_background(const bNode &node, uiBlock &block)
|
|||
|
||||
++panel_i;
|
||||
}
|
||||
|
||||
/* If last item is an open panel, extend the panel background to cover the bottom border. */
|
||||
if (is_last_panel_visible) {
|
||||
UI_block_emboss_set(&block, UI_EMBOSS_NONE);
|
||||
|
||||
const rctf content_rect = {rct.xmin, rct.xmax, rct.ymin, last_panel_content_y};
|
||||
UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
|
||||
UI_draw_roundbox_4fv(&content_rect, true, BASIS_RAD, color_panel);
|
||||
|
||||
UI_block_emboss_set(&block, UI_EMBOSS);
|
||||
}
|
||||
}
|
||||
|
||||
static void node_draw_panels(bNodeTree &ntree, const bNode &node, uiBlock &block)
|
||||
|
@ -1857,7 +1869,7 @@ static void node_draw_panels(bNodeTree &ntree, const bNode &node, uiBlock &block
|
|||
panel_decl->name.c_str(),
|
||||
int(rct.xmin + NODE_MARGIN_X + 0.4f),
|
||||
int(runtime.location_y - NODE_DYS),
|
||||
short(rct.xmax - rct.xmin - 0.35f * U.widget_unit),
|
||||
short(rct.xmax - rct.xmin - (30.0f * UI_SCALE_FAC)),
|
||||
short(NODE_DY),
|
||||
nullptr,
|
||||
0,
|
||||
|
|
|
@ -1022,6 +1022,7 @@ static void node_group_make_insert_selected(const bContext &C,
|
|||
Map<int32_t, int32_t> node_identifier_map;
|
||||
|
||||
ntree.ensure_topology_cache();
|
||||
/* Add all outputs first. */
|
||||
for (bNode *node : nodes_to_move) {
|
||||
for (bNodeSocket *output_socket : node->output_sockets()) {
|
||||
for (bNodeLink *link : output_socket->directly_linked_links()) {
|
||||
|
@ -1047,6 +1048,9 @@ static void node_group_make_insert_selected(const bContext &C,
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Now add all inputs. */
|
||||
for (bNode *node : nodes_to_move) {
|
||||
for (bNodeSocket *input_socket : node->input_sockets()) {
|
||||
for (bNodeLink *link : input_socket->directly_linked_links()) {
|
||||
if (nodeLinkIsHidden(link)) {
|
||||
|
@ -1067,9 +1071,6 @@ static void node_group_make_insert_selected(const bContext &C,
|
|||
if (!info.interface_socket) {
|
||||
info.interface_socket = add_interface_from_socket(ntree, group, *link->tosock);
|
||||
}
|
||||
else {
|
||||
links_to_remove.add(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -911,6 +911,13 @@ static void view3d_id_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
|
|||
ID *id = WM_drag_get_local_ID_or_import_from_asset(C, drag, 0);
|
||||
|
||||
WM_operator_properties_id_lookup_set_from_id(drop->ptr, id);
|
||||
RNA_boolean_set(drop->ptr, "show_datablock_in_modifier", (drag->type != WM_DRAG_ASSET));
|
||||
}
|
||||
|
||||
static void view3d_geometry_nodes_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
|
||||
{
|
||||
view3d_id_drop_copy(C, drag, drop);
|
||||
RNA_boolean_set(drop->ptr, "show_datablock_in_modifier", (drag->type != WM_DRAG_ASSET));
|
||||
}
|
||||
|
||||
static void view3d_id_drop_copy_with_type(bContext *C, wmDrag *drag, wmDropBox *drop)
|
||||
|
@ -1008,7 +1015,7 @@ static void view3d_dropboxes()
|
|||
WM_dropbox_add(lb,
|
||||
"OBJECT_OT_drop_geometry_nodes",
|
||||
view3d_geometry_nodes_drop_poll,
|
||||
view3d_id_drop_copy,
|
||||
view3d_geometry_nodes_drop_copy,
|
||||
WM_drag_free_imported_drag_ID,
|
||||
view3d_geometry_nodes_drop_tooltip);
|
||||
WM_dropbox_add(lb,
|
||||
|
|
|
@ -34,21 +34,9 @@ static void snap_object_data_mesh_get(const Mesh *me_eval,
|
|||
bool use_hide,
|
||||
BVHTreeFromMesh *r_treedata)
|
||||
{
|
||||
const Span<float3> vert_positions = me_eval->vert_positions();
|
||||
const blender::OffsetIndices faces = me_eval->faces();
|
||||
const Span<int> corner_verts = me_eval->corner_verts();
|
||||
|
||||
/* The BVHTree from looptris is always required. */
|
||||
BKE_bvhtree_from_mesh_get(
|
||||
r_treedata, me_eval, use_hide ? BVHTREE_FROM_LOOPTRI_NO_HIDDEN : BVHTREE_FROM_LOOPTRI, 4);
|
||||
|
||||
BLI_assert(reinterpret_cast<const float3 *>(r_treedata->vert_positions) ==
|
||||
vert_positions.data());
|
||||
BLI_assert(r_treedata->corner_verts == corner_verts.data());
|
||||
BLI_assert(!faces.data() || r_treedata->looptri);
|
||||
BLI_assert(!r_treedata->tree || r_treedata->looptri);
|
||||
|
||||
UNUSED_VARS_NDEBUG(vert_positions, faces, corner_verts);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -591,8 +591,6 @@ void split_edges(Mesh &mesh,
|
|||
propagate_vert_attributes(mesh, vert_map);
|
||||
|
||||
BKE_mesh_tag_edges_split(&mesh);
|
||||
|
||||
BLI_assert(BKE_mesh_is_valid(&mesh));
|
||||
}
|
||||
|
||||
} // namespace blender::geometry
|
||||
|
|
|
@ -51,6 +51,7 @@ typedef enum ThumbSource {
|
|||
|
||||
/**
|
||||
* Create thumbnail for file and returns new imbuf for thumbnail.
|
||||
* \param filepath: File path (but not a library path!) to the thumbnail to be created.
|
||||
*/
|
||||
struct ImBuf *IMB_thumb_create(const char *filepath,
|
||||
ThumbSize size,
|
||||
|
@ -59,18 +60,24 @@ struct ImBuf *IMB_thumb_create(const char *filepath,
|
|||
|
||||
/**
|
||||
* Read thumbnail for file and returns new imbuf for thumbnail.
|
||||
* \param file_or_lib_path: File path or library-ID path (e.g. `/a/b.blend/Material/MyMaterial`) to
|
||||
* the thumbnail to be read.
|
||||
*/
|
||||
struct ImBuf *IMB_thumb_read(const char *filepath, ThumbSize size);
|
||||
struct ImBuf *IMB_thumb_read(const char *file_or_lib_path, ThumbSize size);
|
||||
|
||||
/**
|
||||
* Delete all thumbs for the file.
|
||||
* \param file_or_lib_path: File path or library-ID path (e.g. `/a/b.blend/Material/MyMaterial`) to
|
||||
* the thumbnail to be deleted.
|
||||
*/
|
||||
void IMB_thumb_delete(const char *filepath, ThumbSize size);
|
||||
void IMB_thumb_delete(const char *file_or_lib_path, ThumbSize size);
|
||||
|
||||
/**
|
||||
* Create the thumb if necessary and manage failed and old thumbs.
|
||||
* \param file_or_lib_path: File path or library-ID path (e.g. `/a/b.blend/Material/MyMaterial`) to
|
||||
* the thumbnail to be created/managed.
|
||||
*/
|
||||
struct ImBuf *IMB_thumb_manage(const char *filepath, ThumbSize size, ThumbSource source);
|
||||
struct ImBuf *IMB_thumb_manage(const char *file_or_lib_path, ThumbSize size, ThumbSource source);
|
||||
|
||||
/**
|
||||
* Create the necessary directories to store the thumbnails.
|
||||
|
|
|
@ -495,13 +495,13 @@ ImBuf *IMB_thumb_create(const char *filepath, ThumbSize size, ThumbSource source
|
|||
filepath, uri, thumb_name, false, THUMB_DEFAULT_HASH, nullptr, nullptr, size, source, img);
|
||||
}
|
||||
|
||||
ImBuf *IMB_thumb_read(const char *filepath, ThumbSize size)
|
||||
ImBuf *IMB_thumb_read(const char *file_or_lib_path, ThumbSize size)
|
||||
{
|
||||
char thumb[FILE_MAX];
|
||||
char uri[URI_MAX];
|
||||
ImBuf *img = nullptr;
|
||||
|
||||
if (!uri_from_filename(filepath, uri)) {
|
||||
if (!uri_from_filename(file_or_lib_path, uri)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) {
|
||||
|
@ -511,16 +511,16 @@ ImBuf *IMB_thumb_read(const char *filepath, ThumbSize size)
|
|||
return img;
|
||||
}
|
||||
|
||||
void IMB_thumb_delete(const char *filepath, ThumbSize size)
|
||||
void IMB_thumb_delete(const char *file_or_lib_path, ThumbSize size)
|
||||
{
|
||||
char thumb[FILE_MAX];
|
||||
char uri[URI_MAX];
|
||||
|
||||
if (!uri_from_filename(filepath, uri)) {
|
||||
if (!uri_from_filename(file_or_lib_path, uri)) {
|
||||
return;
|
||||
}
|
||||
if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) {
|
||||
if (BLI_path_ncmp(filepath, thumb, sizeof(thumb)) == 0) {
|
||||
if (BLI_path_ncmp(file_or_lib_path, thumb, sizeof(thumb)) == 0) {
|
||||
return;
|
||||
}
|
||||
if (BLI_exists(thumb)) {
|
||||
|
@ -529,18 +529,16 @@ void IMB_thumb_delete(const char *filepath, ThumbSize size)
|
|||
}
|
||||
}
|
||||
|
||||
ImBuf *IMB_thumb_manage(const char *filepath, ThumbSize size, ThumbSource source)
|
||||
ImBuf *IMB_thumb_manage(const char *file_or_lib_path, ThumbSize size, ThumbSource source)
|
||||
{
|
||||
char path_buff[FILE_MAX_LIBEXTRA];
|
||||
/* Will be the actual path to the file, i.e. the same as #filepath or if that points into a
|
||||
* .blend, the path of the .blend. */
|
||||
const char *file_path;
|
||||
const char *path;
|
||||
char *blen_group = nullptr, *blen_id = nullptr;
|
||||
|
||||
path = file_path = filepath;
|
||||
/* Will be the actual path to the file, i.e. the same as #file_or_lib_path, or if that points
|
||||
* into a .blend, the path of the .blend. */
|
||||
const char *file_path = file_or_lib_path;
|
||||
if (source == THB_SOURCE_BLEND) {
|
||||
if (BKE_blendfile_library_path_explode(path, path_buff, &blen_group, &blen_id)) {
|
||||
if (BKE_blendfile_library_path_explode(file_or_lib_path, path_buff, &blen_group, &blen_id)) {
|
||||
if (blen_group) {
|
||||
if (!blen_id) {
|
||||
/* No preview for blen groups */
|
||||
|
@ -556,7 +554,7 @@ ImBuf *IMB_thumb_manage(const char *filepath, ThumbSize size, ThumbSource source
|
|||
return nullptr;
|
||||
}
|
||||
char uri[URI_MAX];
|
||||
if (!uri_from_filename(path, uri)) {
|
||||
if (!uri_from_filename(file_or_lib_path, uri)) {
|
||||
return nullptr;
|
||||
}
|
||||
char thumb_path[FILE_MAX];
|
||||
|
@ -580,8 +578,8 @@ ImBuf *IMB_thumb_manage(const char *filepath, ThumbSize size, ThumbSource source
|
|||
{
|
||||
/* The requested path points to a generated thumbnail already (path into the thumbnail cache
|
||||
* directory). Attempt to load that, there's nothing we can recreate. */
|
||||
if (BLI_path_ncmp(path, thumb_path, sizeof(thumb_path)) == 0) {
|
||||
img = IMB_loadiffname(path, IB_rect, nullptr);
|
||||
if (BLI_path_ncmp(file_or_lib_path, thumb_path, sizeof(thumb_path)) == 0) {
|
||||
img = IMB_loadiffname(file_or_lib_path, IB_rect, nullptr);
|
||||
}
|
||||
else {
|
||||
img = IMB_loadiffname(thumb_path, IB_rect | IB_metadata, nullptr);
|
||||
|
@ -617,9 +615,9 @@ ImBuf *IMB_thumb_manage(const char *filepath, ThumbSize size, ThumbSource source
|
|||
/* recreate all thumbs */
|
||||
IMB_freeImBuf(img);
|
||||
img = nullptr;
|
||||
IMB_thumb_delete(path, THB_NORMAL);
|
||||
IMB_thumb_delete(path, THB_LARGE);
|
||||
IMB_thumb_delete(path, THB_FAIL);
|
||||
IMB_thumb_delete(file_or_lib_path, THB_NORMAL);
|
||||
IMB_thumb_delete(file_or_lib_path, THB_LARGE);
|
||||
IMB_thumb_delete(file_or_lib_path, THB_FAIL);
|
||||
img = thumb_create_or_fail(
|
||||
file_path, uri, thumb_name, use_hash, thumb_hash, blen_group, blen_id, size, source);
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ enum {
|
|||
*
|
||||
* #MLoopTri's are allocated in an array, where each polygon's #MLoopTri's are stored contiguously,
|
||||
* the number of triangles for each polygon is guaranteed to be the corner count - 2,
|
||||
* even for degenerate geometry. See #ME_FACE_TRI_TOT macro.
|
||||
* even for degenerate geometry. See #bke::mesh::face_triangles_num macro.
|
||||
*
|
||||
* It's also possible to perform a reverse lookup (find all #MLoopTri's for any given face).
|
||||
*
|
||||
|
@ -90,7 +90,7 @@ enum {
|
|||
* // loop over all looptri's for a given polygon: i
|
||||
* const IndexRange face = faces[i];
|
||||
* MLoopTri *lt = &looptri[poly_to_tri_count(i, face.start())];
|
||||
* int j, lt_tot = ME_FACE_TRI_TOT(face.size());
|
||||
* int j, lt_tot = bke::mesh::face_triangles_num(face.size());
|
||||
*
|
||||
* for (j = 0; j < lt_tot; j++, lt++) {
|
||||
* int vtri[3] = {
|
||||
|
@ -321,15 +321,6 @@ enum {
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Utility Macros
|
||||
* \{ */
|
||||
|
||||
/** Number of triangles that make up this face once tessellated. */
|
||||
#define ME_FACE_TRI_TOT(face_loop_num) ((face_loop_num)-2)
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Deprecated Structs
|
||||
* \{ */
|
||||
|
|
|
@ -2333,9 +2333,19 @@ typedef struct NodesModifierData {
|
|||
* Directory where baked simulation states are stored. This may be relative to the .blend file.
|
||||
*/
|
||||
char *simulation_bake_directory;
|
||||
|
||||
/** NodesModifierFlag. */
|
||||
int8_t flag;
|
||||
|
||||
char _pad[7];
|
||||
|
||||
NodesModifierRuntimeHandle *runtime;
|
||||
} NodesModifierData;
|
||||
|
||||
typedef enum NodesModifierFlag {
|
||||
NODES_MODIFIER_HIDE_DATABLOCK_SELECTOR = (1 << 0),
|
||||
} NodesModifierFlag;
|
||||
|
||||
typedef struct MeshToVolumeModifierData {
|
||||
ModifierData modifier;
|
||||
|
||||
|
|
|
@ -159,11 +159,6 @@ typedef struct bNodeTreeInterfacePanel {
|
|||
*/
|
||||
bNodeTreeInterfacePanel *find_parent_recursive(const bNodeTreeInterfaceItem &item);
|
||||
|
||||
/**
|
||||
* Create a copy of items in the span and add them to the interface.
|
||||
* \note This does not generate new identifiers for items, use only for identical copies.
|
||||
*/
|
||||
void copy_from(blender::Span<const bNodeTreeInterfaceItem *> items_src, int flag);
|
||||
/** Remove all items from the panel. */
|
||||
void clear(bool do_id_user);
|
||||
|
||||
|
|
|
@ -105,8 +105,8 @@ typedef struct ReportList {
|
|||
#
|
||||
#
|
||||
typedef struct ReportTimerInfo {
|
||||
float col[4];
|
||||
float widthfac;
|
||||
float flash_progress;
|
||||
} ReportTimerInfo;
|
||||
|
||||
//#ifdef WITH_XR_OPENXR
|
||||
|
|
|
@ -2493,6 +2493,14 @@ static void rna_def_library(BlenderRNA *brna)
|
|||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_flag(prop, PROP_THICK_WRAP);
|
||||
|
||||
prop = RNA_def_property(srna, "needs_liboverride_resync", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "tag", LIBRARY_TAG_RESYNC_REQUIRED);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Library Overrides Need resync",
|
||||
"True if this library contains library overrides that are linked in "
|
||||
"current blendfile, and that had to be recursively resynced on load "
|
||||
"(it is recommended to open and re-save that library blendfile then)");
|
||||
|
||||
func = RNA_def_function(srna, "reload", "rna_Library_reload");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_CONTEXT);
|
||||
RNA_def_function_ui_description(func, "Reload this library and all its linked data-blocks");
|
||||
|
|
|
@ -652,7 +652,7 @@ static void rna_MeshPolygon_flip(ID *id, MIntProperty *poly_offset_p)
|
|||
{
|
||||
using namespace blender;
|
||||
Mesh *me = (Mesh *)id;
|
||||
const int index = reinterpret_cast<int *>(poly_offset_p) - me->faces().data();
|
||||
const int index = reinterpret_cast<int *>(poly_offset_p) - me->faces().data().data();
|
||||
bke::mesh_flip_faces(*me, IndexMask(IndexRange(index, 1)));
|
||||
BKE_mesh_tessface_clear(me);
|
||||
BKE_mesh_runtime_clear_geometry(me);
|
||||
|
|
|
@ -7075,6 +7075,13 @@ static void rna_def_modifier_nodes(BlenderRNA *brna)
|
|||
prop, "Simulation Bake Directory", "Location on disk where the bake data is stored");
|
||||
RNA_def_property_update(prop, 0, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "show_group_selector", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(
|
||||
prop, nullptr, "flag", NODES_MODIFIER_HIDE_DATABLOCK_SELECTOR);
|
||||
RNA_def_property_ui_text(prop, "Show Node Group Selector", "");
|
||||
RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE);
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, nullptr);
|
||||
|
||||
RNA_define_lib_overridable(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -1995,6 +1995,15 @@ static void rna_def_menu(BlenderRNA *brna)
|
|||
PropertyRNA *parm;
|
||||
FunctionRNA *func;
|
||||
|
||||
static const EnumPropertyItem menu_flag_items[] = {
|
||||
{int(MenuTypeFlag::SearchOnKeyPress),
|
||||
"SEARCH_ON_KEY_PRESS",
|
||||
0,
|
||||
"Search on Key Press",
|
||||
"Open a menu search when a key pressed while the menu is open"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
srna = RNA_def_struct(brna, "Menu", nullptr);
|
||||
RNA_def_struct_ui_text(srna, "Menu", "Editor menu containing buttons");
|
||||
RNA_def_struct_sdna(srna, "Menu");
|
||||
|
@ -2059,6 +2068,12 @@ static void rna_def_menu(BlenderRNA *brna)
|
|||
RNA_def_property_string_sdna(prop, nullptr, "type->owner_id");
|
||||
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
|
||||
|
||||
prop = RNA_def_property(srna, "bl_options", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, nullptr, "type->flag");
|
||||
RNA_def_property_enum_items(prop, menu_flag_items);
|
||||
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL | PROP_ENUM_FLAG);
|
||||
RNA_def_property_ui_text(prop, "Options", "Options for this menu type");
|
||||
|
||||
RNA_define_verify_sdna(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -1487,16 +1487,18 @@ static void panel_draw(const bContext *C, Panel *panel)
|
|||
* attribute/value toggle requires a manually built layout anyway. */
|
||||
uiLayoutSetPropDecorate(layout, false);
|
||||
|
||||
uiTemplateID(layout,
|
||||
C,
|
||||
ptr,
|
||||
"node_group",
|
||||
"node.new_geometry_node_group_assign",
|
||||
nullptr,
|
||||
nullptr,
|
||||
0,
|
||||
false,
|
||||
nullptr);
|
||||
if (!(nmd->flag & NODES_MODIFIER_HIDE_DATABLOCK_SELECTOR)) {
|
||||
uiTemplateID(layout,
|
||||
C,
|
||||
ptr,
|
||||
"node_group",
|
||||
"node.new_geometry_node_group_assign",
|
||||
nullptr,
|
||||
nullptr,
|
||||
0,
|
||||
false,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
if (nmd->node_group != nullptr && nmd->settings.properties != nullptr) {
|
||||
PointerRNA bmain_ptr = RNA_main_pointer_create(bmain);
|
||||
|
|
|
@ -288,6 +288,7 @@ static void modifier_ops_extra_draw(bContext *C, uiLayout *layout, void *md_v)
|
|||
WM_OP_INVOKE_DEFAULT,
|
||||
UI_ITEM_NONE,
|
||||
&op_ptr);
|
||||
uiItemR(layout, &ptr, "show_group_selector", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -335,8 +335,6 @@ static Mesh *create_uv_sphere_mesh(const float radius,
|
|||
mesh->tag_loose_edges_none();
|
||||
mesh->bounds_set_eager(calculate_bounds_uv_sphere(radius, segments, rings));
|
||||
|
||||
BLI_assert(BKE_mesh_is_valid(mesh));
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
|
|
@ -797,8 +797,11 @@ void SEQ_retiming_sound_animation_data_set(const Scene *scene, const Sequence *s
|
|||
}
|
||||
}
|
||||
else {
|
||||
const int range_start = max_ii(0, range.start);
|
||||
const int range_end = max_ii(0, range.end);
|
||||
|
||||
BKE_sound_set_scene_sound_pitch_constant_range(
|
||||
seq->scene_sound, range.start, range.end, range.speed);
|
||||
seq->scene_sound, range_start, range_end, range.speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1196,7 +1196,7 @@ int WM_operator_confirm_message_ex(bContext *C,
|
|||
uiPopupMenu *pup = UI_popup_menu_begin(C, title, icon);
|
||||
uiLayout *layout = UI_popup_menu_layout(pup);
|
||||
uiItemFullO_ptr(
|
||||
layout, op->type, message, ICON_NONE, properties, opcontext, UI_ITEM_NONE, nullptr);
|
||||
layout, op->type, message, ICON_NONE, properties, opcontext, UI_ITEM_O_DEPRESS, nullptr);
|
||||
UI_popup_menu_end(C, pup);
|
||||
|
||||
return OPERATOR_INTERFACE;
|
||||
|
@ -1741,27 +1741,30 @@ static void WM_OT_operator_defaults(wmOperatorType *ot)
|
|||
enum SearchType {
|
||||
SEARCH_TYPE_OPERATOR = 0,
|
||||
SEARCH_TYPE_MENU = 1,
|
||||
SEARCH_TYPE_SINGLE_MENU = 2,
|
||||
};
|
||||
|
||||
struct SearchPopupInit_Data {
|
||||
SearchType search_type;
|
||||
int size[2];
|
||||
std::string single_menu_idname;
|
||||
};
|
||||
|
||||
static char g_search_text[256] = "";
|
||||
|
||||
static uiBlock *wm_block_search_menu(bContext *C, ARegion *region, void *userdata)
|
||||
{
|
||||
const SearchPopupInit_Data *init_data = static_cast<const SearchPopupInit_Data *>(userdata);
|
||||
static char search[256] = "";
|
||||
|
||||
uiBlock *block = UI_block_begin(C, region, "_popup", UI_EMBOSS);
|
||||
UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
|
||||
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
|
||||
|
||||
uiBut *but = uiDefSearchBut(block,
|
||||
search,
|
||||
g_search_text,
|
||||
0,
|
||||
ICON_VIEWZOOM,
|
||||
sizeof(search),
|
||||
sizeof(g_search_text),
|
||||
10,
|
||||
10,
|
||||
init_data->size[0],
|
||||
|
@ -1776,6 +1779,10 @@ static uiBlock *wm_block_search_menu(bContext *C, ARegion *region, void *userdat
|
|||
else if (init_data->search_type == SEARCH_TYPE_MENU) {
|
||||
UI_but_func_menu_search(but);
|
||||
}
|
||||
else if (init_data->search_type == SEARCH_TYPE_SINGLE_MENU) {
|
||||
UI_but_func_menu_search(but, init_data->single_menu_idname.c_str());
|
||||
UI_but_flag2_enable(but, UI_BUT2_ACTIVATE_ON_INIT_NO_SELECT);
|
||||
}
|
||||
else {
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
|
@ -1837,16 +1844,33 @@ static int wm_search_menu_invoke(bContext *C, wmOperator *op, const wmEvent *eve
|
|||
}
|
||||
}
|
||||
|
||||
int search_type;
|
||||
SearchType search_type;
|
||||
if (STREQ(op->type->idname, "WM_OT_search_menu")) {
|
||||
search_type = SEARCH_TYPE_MENU;
|
||||
}
|
||||
else if (STREQ(op->type->idname, "WM_OT_search_single_menu")) {
|
||||
search_type = SEARCH_TYPE_SINGLE_MENU;
|
||||
}
|
||||
else {
|
||||
search_type = SEARCH_TYPE_OPERATOR;
|
||||
}
|
||||
|
||||
static SearchPopupInit_Data data{};
|
||||
data.search_type = SearchType(search_type);
|
||||
|
||||
if (search_type == SEARCH_TYPE_SINGLE_MENU) {
|
||||
{
|
||||
char *buffer = RNA_string_get_alloc(op->ptr, "menu_idname", nullptr, 0, nullptr);
|
||||
data.single_menu_idname = buffer;
|
||||
MEM_SAFE_FREE(buffer);
|
||||
}
|
||||
{
|
||||
char *buffer = RNA_string_get_alloc(op->ptr, "initial_query", nullptr, 0, nullptr);
|
||||
STRNCPY(g_search_text, buffer);
|
||||
MEM_SAFE_FREE(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
data.search_type = search_type;
|
||||
data.size[0] = UI_searchbox_size_x() * 2;
|
||||
data.size[1] = UI_searchbox_size_y();
|
||||
|
||||
|
@ -1877,6 +1901,25 @@ static void WM_OT_search_operator(wmOperatorType *ot)
|
|||
ot->poll = WM_operator_winactive;
|
||||
}
|
||||
|
||||
static void WM_OT_search_single_menu(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Search Single Menu";
|
||||
ot->idname = "WM_OT_search_single_menu";
|
||||
ot->description = "Pop-up a search for a menu in current context";
|
||||
|
||||
ot->invoke = wm_search_menu_invoke;
|
||||
ot->exec = wm_search_menu_exec;
|
||||
ot->poll = WM_operator_winactive;
|
||||
|
||||
RNA_def_string(ot->srna, "menu_idname", nullptr, 0, "Menu Name", "Menu to search in");
|
||||
RNA_def_string(ot->srna,
|
||||
"initial_query",
|
||||
nullptr,
|
||||
0,
|
||||
"Initial Query",
|
||||
"Query to insert into the search box");
|
||||
}
|
||||
|
||||
static int wm_call_menu_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
char idname[BKE_ST_MAXNAME];
|
||||
|
@ -2024,6 +2067,24 @@ static bool wm_operator_winactive_normal(bContext *C)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool wm_operator_winactive_not_full(bContext *C)
|
||||
{
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
bScreen *screen;
|
||||
|
||||
if (win == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (!((screen = WM_window_get_active_screen(win)) && (screen->state != SCREENFULL))) {
|
||||
return false;
|
||||
}
|
||||
if (G.background) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* included for script-access */
|
||||
static void WM_OT_window_close(wmOperatorType *ot)
|
||||
{
|
||||
|
@ -2042,7 +2103,7 @@ static void WM_OT_window_new(wmOperatorType *ot)
|
|||
ot->description = "Create a new window";
|
||||
|
||||
ot->exec = wm_window_new_exec;
|
||||
ot->poll = wm_operator_winactive_normal;
|
||||
ot->poll = wm_operator_winactive_not_full;
|
||||
}
|
||||
|
||||
static void WM_OT_window_new_main(wmOperatorType *ot)
|
||||
|
@ -3833,6 +3894,7 @@ void wm_operatortypes_register()
|
|||
WM_operatortype_append(WM_OT_splash_about);
|
||||
WM_operatortype_append(WM_OT_search_menu);
|
||||
WM_operatortype_append(WM_OT_search_operator);
|
||||
WM_operatortype_append(WM_OT_search_single_menu);
|
||||
WM_operatortype_append(WM_OT_call_menu);
|
||||
WM_operatortype_append(WM_OT_call_menu_pie);
|
||||
WM_operatortype_append(WM_OT_call_panel);
|
||||
|
|
|
@ -79,6 +79,7 @@ SOURCE_EXT = (
|
|||
"hh",
|
||||
"m",
|
||||
"mm",
|
||||
"metal",
|
||||
"msl",
|
||||
"glsl",
|
||||
"osl",
|
||||
|
|
Loading…
Reference in New Issue