Merge branch 'blender2.8' into blender2.8-workbench

This commit is contained in:
Jeroen Bakker 2018-04-23 20:45:24 +02:00
commit ab10181d57
39 changed files with 534 additions and 408 deletions

4
.gitmodules vendored
View File

@ -3,22 +3,18 @@
url = ../blender-addons.git
branch = blender2.8
ignore = all
branch = master
[submodule "release/scripts/addons_contrib"]
path = release/scripts/addons_contrib
url = ../blender-addons-contrib.git
branch = master
ignore = all
branch = master
[submodule "release/datafiles/locale"]
path = release/datafiles/locale
url = ../blender-translations.git
branch = master
ignore = all
branch = master
[submodule "source/tools"]
path = source/tools
url = ../blender-dev-tools.git
branch = master
ignore = all
branch = master

View File

@ -123,6 +123,7 @@ class SelectCamera(Operator):
def execute(self, context):
scene = context.scene
view_layer = context.view_layer
view = context.space_data
if view.type == 'VIEW_3D' and not view.lock_camera_and_layers:
camera = view.camera
@ -136,8 +137,8 @@ class SelectCamera(Operator):
else:
if not self.extend:
bpy.ops.object.select_all(action='DESELECT')
scene.objects.active = camera
camera.hide = False
view_layer.objects.active = camera
# camera.hide = False # XXX TODO where is this now?
camera.select_set(action='SELECT')
return {'FINISHED'}
@ -171,6 +172,7 @@ class SelectHierarchy(Operator):
def execute(self, context):
scene = context.scene
view_layer = context.view_layer
select_new = []
act_new = None
@ -206,7 +208,7 @@ class SelectHierarchy(Operator):
for obj in select_new:
obj.select_set(action='SELECT')
scene.objects.active = act_new
view_layer.objects.active = act_new
return {'FINISHED'}
return {'CANCELLED'}
@ -881,171 +883,11 @@ class DupliOffsetFromCursor(Operator):
return {'FINISHED'}
class LodByName(Operator):
"""Add levels of detail to this object based on object names"""
bl_idname = "object.lod_by_name"
bl_label = "Setup Levels of Detail By Name"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return (context.active_object is not None)
def execute(self, context):
ob = context.active_object
prefix = ""
suffix = ""
name = ""
if ob.name.lower().startswith("lod0"):
prefix = ob.name[:4]
name = ob.name[4:]
elif ob.name.lower().endswith("lod0"):
name = ob.name[:-4]
suffix = ob.name[-4:]
else:
return {'CANCELLED'}
level = 0
while True:
level += 1
if prefix:
prefix = prefix[:3] + str(level)
if suffix:
suffix = suffix[:3] + str(level)
lod = None
try:
lod = bpy.data.objects[prefix + name + suffix]
except KeyError:
break
try:
ob.lod_levels[level]
except IndexError:
bpy.ops.object.lod_add()
ob.lod_levels[level].object = lod
return {'FINISHED'}
class LodClearAll(Operator):
"""Remove all levels of detail from this object"""
bl_idname = "object.lod_clear_all"
bl_label = "Clear All Levels of Detail"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return (context.active_object is not None)
def execute(self, context):
ob = context.active_object
if ob.lod_levels:
while 'CANCELLED' not in bpy.ops.object.lod_remove():
pass
return {'FINISHED'}
class LodGenerate(Operator):
"""Generate levels of detail using the decimate modifier"""
bl_idname = "object.lod_generate"
bl_label = "Generate Levels of Detail"
bl_options = {'REGISTER', 'UNDO'}
count = IntProperty(
name="Count",
default=3,
)
target = FloatProperty(
name="Target Size",
min=0.0, max=1.0,
default=0.1,
)
package = BoolProperty(
name="Package into Group",
default=False,
)
@classmethod
def poll(cls, context):
return (context.active_object is not None)
def execute(self, context):
scene = context.scene
ob = scene.objects.active
lod_name = ob.name
lod_suffix = "lod"
lod_prefix = ""
if lod_name.lower().endswith("lod0"):
lod_suffix = lod_name[-3:-1]
lod_name = lod_name[:-3]
elif lod_name.lower().startswith("lod0"):
lod_suffix = ""
lod_prefix = lod_name[:3]
lod_name = lod_name[4:]
group_name = lod_name.strip(' ._')
if self.package:
try:
bpy.ops.object.group_link(group=group_name)
except TypeError:
bpy.ops.group.create(name=group_name)
step = (1.0 - self.target) / (self.count - 1)
for i in range(1, self.count):
scene.objects.active = ob
bpy.ops.object.duplicate()
lod = context.selected_objects[0]
scene.objects.active = ob
bpy.ops.object.lod_add()
scene.objects.active = lod
if lod_prefix:
lod.name = lod_prefix + str(i) + lod_name
else:
lod.name = lod_name + lod_suffix + str(i)
lod.location.y = ob.location.y + 3.0 * i
if i == 1:
modifier = lod.modifiers.new("lod_decimate", 'DECIMATE')
else:
modifier = lod.modifiers[-1]
modifier.ratio = 1.0 - step * i
ob.lod_levels[i].object = lod
if self.package:
bpy.ops.object.group_link(group=group_name)
lod.parent = ob
if self.package:
for level in ob.lod_levels[1:]:
level.object.hide = level.object.hide_render = True
lod.select_set(action='DESELECT')
ob.select_set(action='SELECT')
scene.objects.active = ob
return {'FINISHED'}
classes = (
ClearAllRestrictRender,
DupliOffsetFromCursor,
IsolateTypeRender,
JoinUVs,
LodByName,
LodClearAll,
LodGenerate,
MakeDupliFace,
SelectCamera,
SelectHierarchy,

View File

@ -36,10 +36,10 @@ class GRAPH_HT_header(Header):
row = layout.row(align=True)
row.template_header()
GRAPH_MT_editor_menus.draw_collapsible(context, layout)
layout.prop(st, "mode", text="")
GRAPH_MT_editor_menus.draw_collapsible(context, layout)
dopesheet_filter(layout, context)
row = layout.row(align=True)

View File

@ -146,8 +146,9 @@ class TIME_MT_view(Menu):
layout.separator()
layout.operator("time.view_all")
layout.operator("time.view_frame")
# NOTE: "action" now, since timeline is in the dopesheet editor, instead of as own editor
layout.operator("action.view_all")
layout.operator("action.view_frame")
layout.separator()

View File

@ -133,8 +133,7 @@ class TOPBAR_HT_lower_bar(Header):
# Last Action (redo)
layout.label("Last Action:")
operators = context.window_manager.operators
op = operators[-1] if operators else None
op = context.active_operator
row = layout.row()
row.enabled = op is not None
row.popover(

View File

@ -65,8 +65,11 @@ struct Icon {
struct Icon_Geom {
int icon_id;
int coords_len;
int coords_range[2];
const unsigned char (*coords)[2];
const unsigned char (*colors)[4];
/* when not NULL, the memory of coords and colors is a sub-region of this pointer. */
const void *mem;
};
typedef struct Icon Icon;
@ -84,8 +87,6 @@ int BKE_icon_id_ensure(struct ID *id);
int BKE_icon_preview_ensure(struct ID *id, struct PreviewImage *preview);
int BKE_icon_geom_ensure(struct Icon_Geom *geom);
/* retrieve icon for id */
struct Icon *BKE_icon_get(const int icon_id);
@ -149,6 +150,10 @@ struct PreviewImage *BKE_previewimg_cached_thumbnail_read(
void BKE_previewimg_cached_release(const char *name);
void BKE_previewimg_cached_release_pointer(struct PreviewImage *prv);
int BKE_icon_geom_ensure(struct Icon_Geom *geom);
struct Icon_Geom *BKE_icon_geom_from_memory(const uchar *data, size_t data_len);
struct Icon_Geom *BKE_icon_geom_from_file(const char *filename);
struct ImBuf *BKE_icon_geom_rasterize(
const struct Icon_Geom *geom,
const unsigned int size_x, const unsigned int size_y);

View File

@ -51,6 +51,7 @@
#include "BLI_ghash.h"
#include "BLI_linklist_lockfree.h"
#include "BLI_string.h"
#include "BLI_fileops.h"
#include "BLI_threads.h"
#include "BKE_icons.h"
@ -96,8 +97,14 @@ static void icon_free(void *val)
if (icon) {
if (icon->obj_type == ICON_DATA_GEOM) {
struct Icon_Geom *obj = icon->obj;
MEM_freeN((void *)obj->coords);
MEM_freeN((void *)obj->colors);
if (obj->mem) {
/* coords & colors are part of this memory. */
MEM_freeN((void *)obj->mem);
}
else {
MEM_freeN((void *)obj->coords);
MEM_freeN((void *)obj->colors);
}
MEM_freeN(icon->obj);
}
@ -621,22 +628,6 @@ int BKE_icon_preview_ensure(ID *id, PreviewImage *preview)
return preview->icon_id;
}
int BKE_icon_geom_ensure(struct Icon_Geom *geom)
{
BLI_assert(BLI_thread_is_main());
if (geom->icon_id) {
return geom->icon_id;
}
geom->icon_id = get_next_free_id();
icon_create(geom->icon_id, ICON_DATA_GEOM, geom);
/* Not managed for now, we may want this to be configurable per icon). */
return geom->icon_id;
}
Icon *BKE_icon_get(const int icon_id)
{
BLI_assert(BLI_thread_is_main());
@ -735,3 +726,73 @@ bool BKE_icon_delete_unmanaged(const int icon_id)
return false;
}
}
/* -------------------------------------------------------------------- */
/** \name Geometry Icon
* \{ */
int BKE_icon_geom_ensure(struct Icon_Geom *geom)
{
BLI_assert(BLI_thread_is_main());
if (geom->icon_id) {
return geom->icon_id;
}
geom->icon_id = get_next_free_id();
icon_create(geom->icon_id, ICON_DATA_GEOM, geom);
/* Not managed for now, we may want this to be configurable per icon). */
return geom->icon_id;
}
struct Icon_Geom *BKE_icon_geom_from_memory(const uchar *data, size_t data_len)
{
BLI_assert(BLI_thread_is_main());
if (data_len <= 8) {
goto fail;
}
const int div = 3 * 2 * 3;
const int coords_len = (data_len - 8) / div;
if (coords_len * div != data_len) {
goto fail;
}
const uchar header[4] = {'V', 'C', 'O', 0};
const uchar *p = data;
if (memcmp(p, header, ARRAY_SIZE(header)) != 0) {
goto fail;
}
p += 4;
struct Icon_Geom *geom = MEM_mallocN(sizeof(*geom), __func__);
geom->coords_range[0] = (int)*p++;
geom->coords_range[1] = (int)*p++;
/* x, y ignored for now */
p += 2;
geom->coords_len = coords_len;
geom->coords = (const void *)p;
geom->colors = (const void *)(p + (data_len / 3));
geom->icon_id = 0;
geom->mem = data;
return geom;
fail:
MEM_freeN((void *)data);
return NULL;
}
struct Icon_Geom *BKE_icon_geom_from_file(const char *filename)
{
BLI_assert(BLI_thread_is_main());
size_t data_len;
uchar *data = BLI_file_read_binary_as_mem(filename, 0, &data_len);
if (data == NULL) {
return NULL;
}
return BKE_icon_geom_from_memory(data, data_len);
}
/** \} */

View File

@ -134,7 +134,9 @@ static void do_version_area_change_space_to_space_action(ScrArea *area, const Sc
/* Different defaults for timeline */
region_channels = BKE_area_find_region_type(area, RGN_TYPE_CHANNELS);
region_channels->flag |= RGN_FLAG_HIDDEN;
saction->mode = SACTCONT_TIMELINE;
saction->ads.flag |= ADS_FLAG_SUMMARY_COLLAPSED;
}
/**
@ -656,30 +658,33 @@ void do_versions_after_linking_280(Main *main)
const wmWindowManager *wm = main->wm.first;
const Scene *scene = main->scene.first;
/* Action editors need a scene for creation. First, update active
* screens using the active scene of the window they're displayed in.
* Next, update remaining screens using first scene in main listbase. */
if (wm != NULL) {
/* Action editors need a scene for creation. First, update active
* screens using the active scene of the window they're displayed in.
* Next, update remaining screens using first scene in main listbase. */
for (wmWindow *win = wm->windows.first; win; win = win->next) {
const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
for (ScrArea *area = screen->areabase.first; area; area = area->next) {
if (ELEM(area->butspacetype, SPACE_TIME, SPACE_LOGIC)) {
do_version_area_change_space_to_space_action(area, win->scene);
for (wmWindow *win = wm->windows.first; win; win = win->next) {
const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
for (ScrArea *area = screen->areabase.first; area; area = area->next) {
if (ELEM(area->butspacetype, SPACE_TIME, SPACE_LOGIC)) {
do_version_area_change_space_to_space_action(area, win->scene);
/* Don't forget to unset! */
area->butspacetype = SPACE_EMPTY;
/* Don't forget to unset! */
area->butspacetype = SPACE_EMPTY;
}
}
}
}
if (scene != NULL) {
for (bScreen *screen = main->screen.first; screen; screen = screen->id.next) {
for (ScrArea *area = screen->areabase.first; area; area = area->next) {
if (ELEM(area->butspacetype, SPACE_TIME, SPACE_LOGIC)) {
/* Areas that were already handled won't be handled again */
do_version_area_change_space_to_space_action(area, scene);
for (bScreen *screen = main->screen.first; screen; screen = screen->id.next) {
for (ScrArea *area = screen->areabase.first; area; area = area->next) {
if (ELEM(area->butspacetype, SPACE_TIME, SPACE_LOGIC)) {
/* Areas that were already handled won't be handled again */
do_version_area_change_space_to_space_action(area, scene);
/* Don't forget to unset! */
area->butspacetype = SPACE_EMPTY;
/* Don't forget to unset! */
area->butspacetype = SPACE_EMPTY;
}
}
}
}

View File

@ -156,6 +156,9 @@ typedef enum eDepsgraph_Tag {
/* Only inform editors about the change. Don't modify datablock itself. */
DEG_TAG_EDITORS_UPDATE = (1 << 12),
} eDepsgraph_Tag;
const char *DEG_update_tag_as_string(eDepsgraph_Tag flag);
void DEG_id_tag_update(struct ID *id, int flag);
void DEG_id_tag_update_ex(struct Main *bmain, struct ID *id, int flag);

View File

@ -241,13 +241,14 @@ bool DepsgraphRelationBuilder::has_node(const OperationKey &key) const
return find_node(key) != NULL;
}
void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc,
DepsNode *node_to,
const char *description,
bool check_unique)
DepsRelation *DepsgraphRelationBuilder::add_time_relation(
TimeSourceDepsNode *timesrc,
DepsNode *node_to,
const char *description,
bool check_unique)
{
if (timesrc && node_to) {
graph_->add_new_relation(timesrc, node_to, description, check_unique);
return graph_->add_new_relation(timesrc, node_to, description, check_unique);
}
else {
DEG_DEBUG_PRINTF(BUILD, "add_time_relation(%p = %s, %p = %s, %s) Failed\n",
@ -255,16 +256,20 @@ void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc,
node_to, (node_to) ? node_to->identifier().c_str() : "<None>",
description);
}
return NULL;
}
void DepsgraphRelationBuilder::add_operation_relation(
DepsRelation *DepsgraphRelationBuilder::add_operation_relation(
OperationDepsNode *node_from,
OperationDepsNode *node_to,
const char *description,
bool check_unique)
{
if (node_from && node_to) {
graph_->add_new_relation(node_from, node_to, description, check_unique);
return graph_->add_new_relation(node_from,
node_to,
description,
check_unique);
}
else {
DEG_DEBUG_PRINTF(BUILD, "add_operation_relation(%p = %s, %p = %s, %s) Failed\n",
@ -272,6 +277,7 @@ void DepsgraphRelationBuilder::add_operation_relation(
node_to, (node_to) ? node_to->identifier().c_str() : "<None>",
description);
}
return NULL;
}
void DepsgraphRelationBuilder::add_collision_relations(
@ -419,6 +425,8 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
build_object_flags(base, object);
/* Parenting. */
if (object->parent != NULL) {
/* Make sure parent object's relations are built. */
build_object(NULL, object->parent);
/* Parent relationship. */
build_object_parent(object);
/* Local -> parent. */
@ -2007,6 +2015,9 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDDepsNode *id_node
/* All dangling operations should also be executed after copy-on-write. */
GHASH_FOREACH_BEGIN(OperationDepsNode *, op_node, comp_node->operations_map)
{
if (op_node == op_entry) {
continue;
}
if (op_node->inlinks.size() == 0) {
graph_->add_new_relation(op_cow, op_node, "CoW Dependency");
}

View File

@ -83,6 +83,7 @@ namespace DEG {
struct Depsgraph;
struct DepsNode;
struct DepsNodeHandle;
struct DepsRelation;
struct RootDepsNode;
struct IDDepsNode;
struct TimeSourceDepsNode;
@ -176,22 +177,22 @@ struct DepsgraphRelationBuilder
void begin_build();
template <typename KeyFrom, typename KeyTo>
void add_relation(const KeyFrom& key_from,
const KeyTo& key_to,
const char *description,
bool check_unique = false);
DepsRelation *add_relation(const KeyFrom& key_from,
const KeyTo& key_to,
const char *description,
bool check_unique = false);
template <typename KeyTo>
void add_relation(const TimeSourceKey& key_from,
const KeyTo& key_to,
const char *description,
bool check_unique = false);
DepsRelation *add_relation(const TimeSourceKey& key_from,
const KeyTo& key_to,
const char *description,
bool check_unique = false);
template <typename KeyType>
void add_node_handle_relation(const KeyType& key_from,
const DepsNodeHandle *handle,
const char *description,
bool check_unique = false);
DepsRelation *add_node_handle_relation(const KeyType& key_from,
const DepsNodeHandle *handle,
const char *description,
bool check_unique = false);
void build_view_layer(Scene *scene, ViewLayer *view_layer);
void build_group(Object *object, Group *group);
@ -280,14 +281,14 @@ protected:
OperationDepsNode *find_node(const OperationKey &key) const;
bool has_node(const OperationKey &key) const;
void add_time_relation(TimeSourceDepsNode *timesrc,
DepsNode *node_to,
const char *description,
bool check_unique = false);
void add_operation_relation(OperationDepsNode *node_from,
OperationDepsNode *node_to,
const char *description,
bool check_unique = false);
DepsRelation *add_time_relation(TimeSourceDepsNode *timesrc,
DepsNode *node_to,
const char *description,
bool check_unique = false);
DepsRelation *add_operation_relation(OperationDepsNode *node_from,
OperationDepsNode *node_to,
const char *description,
bool check_unique = false);
template <typename KeyType>
DepsNodeHandle create_node_handle(const KeyType& key,

View File

@ -46,17 +46,17 @@ OperationDepsNode *DepsgraphRelationBuilder::find_operation_node(const KeyType&
}
template <typename KeyFrom, typename KeyTo>
void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
const KeyTo &key_to,
const char *description,
bool check_unique)
DepsRelation *DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
const KeyTo &key_to,
const char *description,
bool check_unique)
{
DepsNode *node_from = get_node(key_from);
DepsNode *node_to = get_node(key_to);
OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
if (op_from && op_to) {
add_operation_relation(op_from, op_to, description, check_unique);
return add_operation_relation(op_from, op_to, description, check_unique);
}
else {
if (!op_from) {
@ -78,24 +78,27 @@ void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
description, key_to.identifier().c_str());
}
}
return NULL;
}
template <typename KeyTo>
void DepsgraphRelationBuilder::add_relation(const TimeSourceKey &key_from,
const KeyTo &key_to,
const char *description,
bool check_unique)
DepsRelation *DepsgraphRelationBuilder::add_relation(
const TimeSourceKey &key_from,
const KeyTo &key_to,
const char *description,
bool check_unique)
{
TimeSourceDepsNode *time_from = get_node(key_from);
DepsNode *node_to = get_node(key_to);
OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
if (time_from != NULL && op_to != NULL) {
add_time_relation(time_from, op_to, description, check_unique);
return add_time_relation(time_from, op_to, description, check_unique);
}
return NULL;
}
template <typename KeyType>
void DepsgraphRelationBuilder::add_node_handle_relation(
DepsRelation *DepsgraphRelationBuilder::add_node_handle_relation(
const KeyType &key_from,
const DepsNodeHandle *handle,
const char *description,
@ -105,7 +108,7 @@ void DepsgraphRelationBuilder::add_node_handle_relation(
OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
OperationDepsNode *op_to = handle->node->get_entry_operation();
if (op_from != NULL && op_to != NULL) {
add_operation_relation(op_from, op_to, description, check_unique);
return add_operation_relation(op_from, op_to, description, check_unique);
}
else {
if (!op_from) {
@ -117,6 +120,7 @@ void DepsgraphRelationBuilder::add_node_handle_relation(
description, key_from.identifier().c_str());
}
}
return NULL;
}
template <typename KeyType>

View File

@ -259,6 +259,18 @@ static void deg_debug_graphviz_relation_color(const DebugContext &ctx,
deg_debug_fprintf(ctx, "%s", color);
}
static void deg_debug_graphviz_relation_style(const DebugContext &ctx,
const DepsRelation *rel)
{
const char *style_default = "solid";
const char *style_no_flush = "dashed";
const char *style = style_default;
if (rel->flag & DEPSREL_FLAG_NO_FLUSH) {
style = style_no_flush;
}
deg_debug_fprintf(ctx, "%s", style);
}
static void deg_debug_graphviz_node_style(const DebugContext &ctx, const DepsNode *node)
{
const char *base_style = "filled"; /* default style */
@ -468,16 +480,23 @@ static void deg_debug_graphviz_node_relations(const DebugContext &ctx,
/* Note: without label an id seem necessary to avoid bugs in graphviz/dot */
deg_debug_fprintf(ctx, "id=\"%s\"", rel->name);
// deg_debug_fprintf(ctx, "label=\"%s\"", rel->name);
deg_debug_fprintf(ctx, ",color="); deg_debug_graphviz_relation_color(ctx, rel);
deg_debug_fprintf(ctx, ",color=");
deg_debug_graphviz_relation_color(ctx, rel);
deg_debug_fprintf(ctx, ",style=");
deg_debug_graphviz_relation_style(ctx, rel);
deg_debug_fprintf(ctx, ",penwidth=\"%f\"", penwidth);
/* NOTE: edge from node to own cluster is not possible and gives graphviz
* warning, avoid this here by just linking directly to the invisible
* placeholder node
*/
if (deg_debug_graphviz_is_cluster(tail) && !deg_debug_graphviz_is_owner(head, tail)) {
if (deg_debug_graphviz_is_cluster(tail) &&
!deg_debug_graphviz_is_owner(head, tail))
{
deg_debug_fprintf(ctx, ",ltail=\"cluster_%p\"", tail);
}
if (deg_debug_graphviz_is_cluster(head) && !deg_debug_graphviz_is_owner(tail, head)) {
if (deg_debug_graphviz_is_cluster(head) &&
!deg_debug_graphviz_is_owner(tail, head))
{
deg_debug_fprintf(ctx, ",lhead=\"cluster_%p\"", head);
}
deg_debug_fprintf(ctx, "];" NL);

View File

@ -236,6 +236,11 @@ static bool pointer_to_component_node_criteria(
*type = DEG_NODE_TYPE_SHADING;
return true;
}
else if (ptr->type == &RNA_Curve) {
*id = (ID *)ptr->id.data;
*type = DEG_NODE_TYPE_GEOMETRY;
return true;
}
if (prop != NULL) {
/* All unknown data effectively falls under "parameter evaluation". */
if (RNA_property_is_idprop(prop)) {

View File

@ -64,13 +64,12 @@ struct OperationDepsNode;
/* Settings/Tags on Relationship */
typedef enum eDepsRelation_Flag {
/* "touched" tag is used when filtering, to know which to collect */
DEPSREL_FLAG_TEMP_TAG = (1 << 0),
/* "cyclic" link - when detecting cycles, this relationship was the one
* which triggers a cyclic relationship to exist in the graph
* which triggers a cyclic relationship to exist in the graph.
*/
DEPSREL_FLAG_CYCLIC = (1 << 1),
DEPSREL_FLAG_CYCLIC = (1 << 0),
/* Update flush will not go through this relation. */
DEPSREL_FLAG_NO_FLUSH = (1 << 1),
} eDepsRelation_Flag;
/* B depends on A (A -> B) */

View File

@ -473,10 +473,64 @@ void deg_graph_on_visible_update(Main *bmain, Depsgraph *graph)
}
}
string stringify_append_bit(const string& str, eDepsgraph_Tag tag)
{
string result = str;
if (!result.empty()) {
result += ", ";
}
result += DEG_update_tag_as_string(tag);
return result;
}
string stringify_update_bitfield(int flag)
{
if (flag == 0) {
return "LEGACY_0";
}
string result = "";
int current_flag = flag;
/* Special cases to avoid ALL flags form being split into
* individual bits.
*/
if ((current_flag & DEG_TAG_PSYS_ALL) == DEG_TAG_PSYS_ALL) {
result = stringify_append_bit(result, DEG_TAG_PSYS_ALL);
}
/* Handle all the rest of the flags. */
while (current_flag != 0) {
eDepsgraph_Tag tag =
(eDepsgraph_Tag)(1 << bitscan_forward_clear_i(&current_flag));
result = stringify_append_bit(result, tag);
}
return result;
}
} /* namespace */
} // namespace DEG
const char *DEG_update_tag_as_string(eDepsgraph_Tag flag)
{
switch (flag) {
case DEG_TAG_TRANSFORM: return "TRANSFORM";
case DEG_TAG_GEOMETRY: return "GEOMETRY";
case DEG_TAG_TIME: return "TIME";
case DEG_TAG_PSYS_REDO: return "PSYS_REDO";
case DEG_TAG_PSYS_RESET: return "PSYS_RESET";
case DEG_TAG_PSYS_TYPE: return "PSYS_TYPE";
case DEG_TAG_PSYS_CHILD: return "PSYS_CHILD";
case DEG_TAG_PSYS_PHYS: return "PSYS_PHYS";
case DEG_TAG_PSYS_ALL: return "PSYS_ALL";
case DEG_TAG_COPY_ON_WRITE: return "COPY_ON_WRITE";
case DEG_TAG_SHADING_UPDATE: return "SHADING_UPDATE";
case DEG_TAG_SELECT_UPDATE: return "SELECT_UPDATE";
case DEG_TAG_BASE_FLAGS_UPDATE: return "BASE_FLAGS_UPDATE";
case DEG_TAG_EDITORS_UPDATE: return "EDITORS_UPDATE";
}
BLI_assert(!"Unhandled update flag, should never happen!");
return "UNKNOWN";
}
/* Data-Based Tagging */
/* Tag given ID for an update in all the dependency graphs. */
@ -492,7 +546,10 @@ void DEG_id_tag_update_ex(Main *bmain, ID *id, int flag)
return;
}
if (G.debug & G_DEBUG_DEPSGRAPH_TAG) {
printf("%s: id=%s flag=%d\n", __func__, id->name, flag);
printf("%s: id=%s flags=%s\n",
__func__,
id->name,
DEG::stringify_update_bitfield(flag).c_str());
}
DEG::deg_id_tag_update(bmain, id, flag);
}

View File

@ -182,6 +182,9 @@ BLI_INLINE OperationDepsNode *flush_schedule_children(
{
OperationDepsNode *result = NULL;
foreach (DepsRelation *rel, op_node->outlinks) {
if (rel->flag & DEPSREL_FLAG_NO_FLUSH) {
continue;
}
OperationDepsNode *to_node = (OperationDepsNode *)rel->to;
if (to_node->scheduled == false) {
if (result != NULL) {

View File

@ -652,19 +652,24 @@ void DRW_draw_cursor(void)
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
glLineWidth(1.0f);
if (is_cursor_visible(draw_ctx, scene, view_layer)) {
int co[2];
if (ED_view3d_project_int_global(ar, ED_view3d_cursor3d_get(scene, v3d), co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
ED_region_pixelspace(ar);
gpuTranslate2f(co[0], co[1]);
gpuTranslate2f(co[0] + 0.5f, co[1] + 0.5f);
gpuScale2f(U.widget_unit, U.widget_unit);
Gwn_Batch *cursor_batch = DRW_cache_cursor_get();
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_FLAT_COLOR);
GWN_batch_program_set(cursor_batch, GPU_shader_get_program(shader), GPU_shader_get_interface(shader));
/* Draw nice Anti Aliased cursor. */
glLineWidth(1.0f);
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
GWN_batch_draw(cursor_batch);
}
}

View File

@ -307,9 +307,6 @@ static void selectconnected_posebonechildren(Object *ob, Bone *bone, int extend)
if (!(bone->flag & BONE_CONNECTED) || (bone->flag & BONE_UNSELECTABLE))
return;
/* XXX old cruft! use notifiers instead */
//select_actionchannel_by_name (ob->action, bone->name, !(shift));
if (extend)
bone->flag &= ~BONE_SELECTED;
else
@ -381,7 +378,7 @@ void POSE_OT_select_linked(wmOperatorType *ot)
ot->idname = "POSE_OT_select_linked";
ot->description = "Select bones related to selected ones by parent/child relationships";
/* api callbacks */
/* callbacks */
/* leave 'exec' unset */
ot->invoke = pose_select_connected_invoke;
ot->poll = pose_select_linked_poll;

View File

@ -758,6 +758,7 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op,
void (*clear_func)(bPoseChannel *), const char default_ksName[])
{
Scene *scene = CTX_data_scene(C);
bool changed_multi = false;
/* sanity checks */
if (ELEM(NULL, clear_func, default_ksName)) {
@ -765,17 +766,15 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op,
return OPERATOR_CANCELLED;
}
bool changed_multi = false;
/* only clear relevant transforms for selected bones */
ViewLayer *view_layer = CTX_data_view_layer(C);
FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, OB_MODE_POSE, ob_iter) {
FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, OB_MODE_POSE, ob_iter)
{
ListBase dsources = {NULL, NULL};
bool changed = false;
FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob_iter, pchan) {
FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob_iter, pchan)
{
/* run provided clearing function */
clear_func(pchan);
changed = true;
@ -795,7 +794,8 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op,
pchan->bone->flag |= BONE_UNKEYED;
}
}
} FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
}
FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
if (changed) {
changed_multi = true;
@ -821,7 +821,8 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op,
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob_iter);
}
} FOREACH_OBJECT_IN_MODE_END;
}
FOREACH_OBJECT_IN_MODE_END;
return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
@ -916,57 +917,61 @@ void POSE_OT_transforms_clear(wmOperatorType *ot)
static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
{
ViewLayer *view_layer = CTX_data_view_layer(C);
Scene *scene = CTX_data_scene(C);
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
float cframe = (float)CFRA;
const bool only_select = RNA_boolean_get(op->ptr, "only_selected");
if ((ob->adt) && (ob->adt->action)) {
/* XXX: this is just like this to avoid contaminating anything else;
* just pose values should change, so this should be fine
*/
bPose *dummyPose = NULL;
Object workob = {{NULL}};
bPoseChannel *pchan;
/* execute animation step for current frame using a dummy copy of the pose */
BKE_pose_copy_data(&dummyPose, ob->pose, 0);
BLI_strncpy(workob.id.name, "OB<ClearTfmWorkOb>", sizeof(workob.id.name));
workob.type = OB_ARMATURE;
workob.data = ob->data;
workob.adt = ob->adt;
workob.pose = dummyPose;
BKE_animsys_evaluate_animdata(scene, &workob.id, workob.adt, cframe, ADT_RECALC_ANIM);
/* copy back values, but on selected bones only */
for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
pose_bone_do_paste(ob, pchan, only_select, 0);
}
/* free temp data - free manually as was copied without constraints */
for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
if (pchan->prop) {
IDP_FreeProperty(pchan->prop);
MEM_freeN(pchan->prop);
FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, OB_MODE_POSE, ob)
{
if ((ob->adt) && (ob->adt->action)) {
/* XXX: this is just like this to avoid contaminating anything else;
* just pose values should change, so this should be fine
*/
bPose *dummyPose = NULL;
Object workob = {{NULL}};
bPoseChannel *pchan;
/* execute animation step for current frame using a dummy copy of the pose */
BKE_pose_copy_data(&dummyPose, ob->pose, 0);
BLI_strncpy(workob.id.name, "OB<ClearTfmWorkOb>", sizeof(workob.id.name));
workob.type = OB_ARMATURE;
workob.data = ob->data;
workob.adt = ob->adt;
workob.pose = dummyPose;
BKE_animsys_evaluate_animdata(scene, &workob.id, workob.adt, cframe, ADT_RECALC_ANIM);
/* copy back values, but on selected bones only */
for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
pose_bone_do_paste(ob, pchan, only_select, 0);
}
/* free temp data - free manually as was copied without constraints */
for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
if (pchan->prop) {
IDP_FreeProperty(pchan->prop);
MEM_freeN(pchan->prop);
}
}
/* was copied without constraints */
BLI_freelistN(&dummyPose->chanbase);
MEM_freeN(dummyPose);
}
else {
/* no animation, so just reset whole pose to rest pose
* (cannot just restore for selected though)
*/
BKE_pose_rest(ob->pose);
}
/* was copied without constraints */
BLI_freelistN(&dummyPose->chanbase);
MEM_freeN(dummyPose);
/* notifiers and updates */
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
}
else {
/* no animation, so just reset whole pose to rest pose
* (cannot just restore for selected though)
*/
BKE_pose_rest(ob->pose);
}
/* notifiers and updates */
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
FOREACH_OBJECT_IN_MODE_END;
return OPERATOR_FINISHED;
}

View File

@ -6777,6 +6777,7 @@ static bool ui_but_menu(bContext *C, uiBut *but)
if (but->flag & UI_BUT_OVERRIDEN) {
if (is_array_component) {
#if 0 /* Disabled for now. */
ot = WM_operatortype_find("UI_OT_override_type_set_button", false);
uiItemFullO_ptr(layout, ot, "Overrides Type", ICON_NONE,
NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
@ -6784,17 +6785,18 @@ static bool ui_but_menu(bContext *C, uiBut *but)
uiItemFullO_ptr(layout, ot, "Single Override Type", ICON_NONE,
NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
RNA_boolean_set(&op_ptr, "all", false);
#endif
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Overrides"),
ICON_X, "UI_OT_override_remove_button", "all", true);
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Single Override"),
ICON_X, "UI_OT_override_remove_button", "all", false);
}
else {
#if 0 /* Disabled for now. */
uiItemFullO(layout, "UI_OT_override_type_set_button", "Override Type", ICON_NONE,
NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
RNA_boolean_set(&op_ptr, "all", false);
#endif
uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Override"),
ICON_X, "UI_OT_override_remove_button", "all", true);
}

View File

@ -540,7 +540,12 @@ static int override_type_set_button_exec(bContext *C, wmOperator *op)
static int override_type_set_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
#if 0 /* Disabled for now */
return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_DEFAULT);
#else
RNA_enum_set(op->ptr, "type", IDOVERRIDESTATIC_OP_REPLACE);
return override_type_set_button_exec(C, op);
#endif
}
static void UI_OT_override_type_set_button(wmOperatorType *ot)
@ -562,7 +567,7 @@ static void UI_OT_override_type_set_button(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
ot->prop = RNA_def_enum(ot->srna, "type", override_type_items, UIOverride_Type_Replace,
"Type", "Type of override operation");
/* TODO: add itemf callback, not all aoptions are available for all data types... */
/* TODO: add itemf callback, not all options are available for all data types... */
}

View File

@ -136,9 +136,11 @@ static uiBut *ui_popup_menu_memory__internal(uiBlock *block, uiBut *but)
}
else {
/* get */
for (but = block->buttons.first; but; but = but->next)
if (ui_popup_string_hash(but->str) == mem[hash_mod])
for (but = block->buttons.first; but; but = but->next) {
if (ui_popup_string_hash(but->str) == mem[hash_mod]) {
return but;
}
}
return NULL;
}
@ -176,9 +178,8 @@ struct uiPopupMenu {
static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, void *arg_pup)
{
uiBlock *block;
uiBut *bt;
uiPopupMenu *pup = arg_pup;
int offset[2], minwidth, width, height;
int minwidth, width, height;
char direction;
bool flip;
@ -218,8 +219,9 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
/* in some cases we create the block before the region,
* so we set it delayed here if necessary */
if (BLI_findindex(&handle->region->uiblocks, block) == -1)
if (BLI_findindex(&handle->region->uiblocks, block) == -1) {
UI_block_region_set(block, handle->region);
}
block->direction = direction;
@ -228,6 +230,9 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT);
if (pup->popup) {
uiBut *bt;
int offset[2];
uiBut *but_activate = NULL;
UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_NUMSELECT);
UI_block_direction_set(block, direction);
@ -251,8 +256,9 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
/* position mouse at 0.8*width of the button and below the tile
* on the first item */
offset[0] = 0;
for (bt = block->buttons.first; bt; bt = bt->next)
for (bt = block->buttons.first; bt; bt = bt->next) {
offset[0] = min_ii(offset[0], -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect)));
}
offset[1] = 2.1 * UI_UNIT_Y;
@ -292,8 +298,9 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
}
/* if menu slides out of other menu, override direction */
if (pup->slideout)
if (pup->slideout) {
UI_block_direction_set(block, UI_DIR_RIGHT);
}
return pup->block;
}
@ -334,8 +341,9 @@ uiPopupBlockHandle *ui_popup_menu_create(
pup->block->flag |= UI_BLOCK_NO_FLIP;
}
#endif
if (but->context)
if (but->context) {
uiLayoutContextCopy(pup->layout, but->context);
}
}
/* menu is created from a callback */

View File

@ -36,7 +36,7 @@
* - UI is not constrained to a list.
* - Pressing a button won't close the pop-over.
* - Different draw style (to show this is has different behavior from a menu).
* - #PanelType are used insetead of #MenuType.
* - #PanelType are used instead of #MenuType.
* - No menu flipping support.
* - No moving the menu to fit the mouse cursor.
* - No key accelerators to access menu items
@ -46,38 +46,23 @@
* - No title.
*/
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "MEM_guardedalloc.h"
#include "DNA_userdef_types.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_rect.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_report.h"
#include "WM_api.h"
#include "WM_types.h"
#include "RNA_access.h"
#include "UI_interface.h"
#include "BLT_translation.h"
#include "ED_screen.h"
#include "interface_intern.h"
#include "interface_regions_intern.h"
@ -102,7 +87,7 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
{
uiBlock *block;
uiPopover *pup = arg_pup;
int offset[2], minwidth, width, height;
int minwidth, width, height;
if (pup->menu_func) {
pup->block->handle = handle;
@ -134,6 +119,7 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
const int block_margin = U.widget_unit / 2;
if (pup->popover) {
int offset[2] = {0, 0}; /* Dummy. */
UI_block_flag_enable(block, UI_BLOCK_LOOP);
UI_block_direction_set(block, block->direction);
block->minbounds = minwidth;
@ -182,8 +168,9 @@ uiPopupBlockHandle *ui_popover_panel_create(
* reverse some enum's but not others, so reverse all so the first menu
* items are always close to the mouse cursor */
else {
if (but->context)
if (but->context) {
uiLayoutContextCopy(pup->layout, but->context);
}
}
/* menu is created from a callback */
@ -221,7 +208,9 @@ uiPopover *UI_popover_begin_ex(bContext *C, const char *block_name)
uiPopover *pup = MEM_callocN(sizeof(uiPopover), "popover menu");
pup->block = UI_block_begin(C, NULL, block_name, UI_EMBOSS);
pup->layout = UI_block_layout(pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 0, MENU_PADDING, style);
pup->layout = UI_block_layout(
pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0,
U.widget_unit * UI_POPOVER_WIDTH_UNITS, 0, MENU_PADDING, style);
/* Copied from menus, change if needed. */
uiLayoutSetOperatorContext(pup->layout, WM_OP_EXEC_REGION_WIN);
@ -282,6 +271,6 @@ uiLayout *UI_popover_layout(uiPopover *pup)
/** \} */
/* We may want to support this in futurew */
/* We may want to support this in future */
/* Similar to UI_popup_menu_invoke */
// int UI_popover_panel_invoke(bContext *C, const char *idname, ReportList *reports);

View File

@ -2730,7 +2730,7 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir
glDisable(GL_BLEND);
}
static void widget_popover_back(uiWidgetColors *wcol, rcti *rect, int flag, int direction)
static void widget_popover_back(uiWidgetColors *wcol, rcti *rect, int UNUSED(flag), int direction)
{
/* tsk, this isn't nice. */
const float unit_half = (BLI_rcti_size_x(rect) / UI_POPOVER_WIDTH_UNITS) / 2;
@ -2738,22 +2738,46 @@ static void widget_popover_back(uiWidgetColors *wcol, rcti *rect, int flag, int
rect->ymax -= unit_half;
rect->ymin += unit_half;
widget_menu_back(wcol, rect, flag, direction);
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ubv((unsigned char *)wcol->inner);
glEnable(GL_BLEND);
immBegin(GWN_PRIM_TRIS, 3);
immVertex2f(pos, cent_x - unit_half, rect->ymax);
immVertex2f(pos, cent_x + unit_half, rect->ymax);
immVertex2f(pos, cent_x, rect->ymax + unit_half);
immEnd();
/* Extracted from 'widget_menu_back', keep separate to avoid menu changes breaking popovers */
{
uiWidgetBase wtb;
widget_init(&wtb);
const int roundboxalign = UI_CNR_ALL;
widget_softshadow(rect, roundboxalign, wcol->roundness * U.widget_unit);
round_box_edges(&wtb, roundboxalign, rect, wcol->roundness * U.widget_unit);
wtb.draw_emboss = false;
widgetbase_draw(&wtb, wcol);
}
/* Draw popover arrow (top/bottom) */
if (ELEM(direction, UI_DIR_UP, UI_DIR_DOWN)) {
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ubv((unsigned char *)wcol->inner);
glEnable(GL_BLEND);
immBegin(GWN_PRIM_TRIS, 3);
if (direction == UI_DIR_DOWN) {
const float y = rect->ymax;
immVertex2f(pos, cent_x - unit_half, y);
immVertex2f(pos, cent_x + unit_half, y);
immVertex2f(pos, cent_x, y + unit_half);
}
else {
const float y = rect->ymin;
immVertex2f(pos, cent_x - unit_half, y);
immVertex2f(pos, cent_x + unit_half, rect->ymin);
immVertex2f(pos, cent_x, y - unit_half);
}
immEnd();
immUnbindProgram();
}
glDisable(GL_BLEND);
immUnbindProgram();
}
static void ui_hsv_cursor(float x, float y)
@ -4293,7 +4317,7 @@ static int widget_roundbox_set(uiBut *but, rcti *rect)
}
/* align with open menu */
if (but->active) {
if (but->active && (but->type != UI_BTYPE_POPOVER)) {
int direction = ui_but_menu_direction(but);
if (direction == UI_DIR_UP) roundbox &= ~(UI_CNR_TOP_RIGHT | UI_CNR_TOP_LEFT);

View File

@ -261,10 +261,6 @@ void OBJECT_OT_grouped_select(struct wmOperatorType *ot);
void OBJECT_OT_bake_image(wmOperatorType *ot);
void OBJECT_OT_bake(wmOperatorType *ot);
/* object_lod.c */
void OBJECT_OT_lod_add(struct wmOperatorType *ot);
void OBJECT_OT_lod_remove(struct wmOperatorType *ot);
/* object_random.c */
void TRANSFORM_OT_vertex_random(struct wmOperatorType *ot);

View File

@ -660,13 +660,6 @@ static void area_azone_initialize(wmWindow *win, const bScreen *screen, ScrArea
return;
}
/* can't click on bottom corners on OS X, already used for resizing */
#ifdef __APPLE__
if (!(sa->totrct.xmin == 0 && sa->totrct.ymin == 0) || WM_window_is_fullscreen(win))
#else
(void)win;
#endif
float coords[4][4] = {
/* Bottom-left. */
{sa->totrct.xmin,
@ -690,6 +683,17 @@ static void area_azone_initialize(wmWindow *win, const bScreen *screen, ScrArea
sa->totrct.ymax - (AZONESPOT - 1)}};
for (int i = 0; i < 4; i++) {
/* can't click on bottom corners on OS X, already used for resizing */
#ifdef __APPLE__
if (!WM_window_is_fullscreen(win) &&
((coords[i][0] == 0 && coords[i][1] == 0) ||
(coords[i][0] == WM_window_pixels_x(win) && coords[i][1] == 0))) {
continue;
}
#else
(void)win;
#endif
/* set area action zones */
az = (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
BLI_addtail(&(sa->actionzones), az);

View File

@ -286,9 +286,9 @@ static void drawscredge_corner(ScrArea *sa, int sizex, int sizey)
/* Bottom-Left. */
drawscredge_corner_geometry(sizex, sizey,
sa->v1->vec.x,
sa->v1->vec.y,
sa->v1->vec.x + size,
sa->v1->vec.y + size,
sa->v1->vec.y,
sa->v1->vec.x + size,
sa->v1->vec.y + size,
M_PI_2 * 2.0f,
color);

View File

@ -277,6 +277,7 @@ static void animrecord_check_state(Scene *scene, ID *id, wmTimer *animtimer)
/* if playback has just looped around, we need to add a new NLA track+strip to allow a clean pass to occur */
if ((sad) && (sad->flag & ANIMPLAY_FLAG_JUMPED)) {
AnimData *adt = BKE_animdata_from_id(id);
const bool is_first = (adt) && (adt->nla_tracks.first == NULL);
/* perform push-down manually with some differences
* NOTE: BKE_nla_action_pushdown() sync warning...
@ -297,6 +298,29 @@ static void animrecord_check_state(Scene *scene, ID *id, wmTimer *animtimer)
strip->extendmode = NLASTRIP_EXTEND_NOTHING;
strip->flag &= ~(NLASTRIP_FLAG_AUTO_BLENDS | NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_ACTIVE);
/* copy current "action blending" settings from adt to the strip,
* as it was keyframed with these settings, so omitting them will
* change the effect [T54766]
*/
if (is_first == false) {
strip->blendmode = adt->act_blendmode;
strip->influence = adt->act_influence;
if (adt->act_influence < 1.0f) {
/* enable "user-controlled" influence (which will insert a default keyframe)
* so that the influence doesn't get lost on the new update
*
* NOTE: An alternative way would have been to instead hack the influence
* to not get always get reset to full strength if NLASTRIP_FLAG_USR_INFLUENCE
* is disabled but auto-blending isn't being used. However, that approach
* is a bit hacky/hard to discover, and may cause backwards compatability issues,
* so it's better to just do it this way.
*/
strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
BKE_nlastrip_validate_fcurves(strip);
}
}
/* also, adjust the AnimData's action extend mode to be on
* 'nothing' so that previous result still play
*/

View File

@ -7506,19 +7506,21 @@ bool RNA_struct_override_matches(
continue;
}
#if 0 /* This actually makes things slower, since it has to check for animation paths etc! */
if (RNA_property_animated(ptr_local, prop_local)) {
/* We cannot do anything here really, animation is some kind of dynamic overrides that has
* precedence over static one... */
continue;
}
#endif
#define RNA_PATH_BUFFSIZE 8192
#define RNA_PATH_PRINTF(_str, ...) \
if (BLI_snprintf(rna_path, RNA_PATH_BUFFSIZE, \
(_str), __VA_ARGS__) >= RNA_PATH_BUFFSIZE) \
{ rna_path = BLI_sprintfN((_str), __VA_ARGS__); }(void)0
if (BLI_snprintf(rna_path, RNA_PATH_BUFFSIZE, \
(_str), __VA_ARGS__) >= RNA_PATH_BUFFSIZE) \
{ rna_path = BLI_sprintfN((_str), __VA_ARGS__); }(void)0
#define RNA_PATH_FREE \
if (rna_path != rna_path_buffer) MEM_freeN(rna_path)
if (rna_path != rna_path_buffer) MEM_freeN(rna_path)
char rna_path_buffer[RNA_PATH_BUFFSIZE];
char *rna_path = rna_path_buffer;

View File

@ -2484,10 +2484,12 @@ void RNA_def_constraint(BlenderRNA *brna)
/* flags */
prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_OFF);
RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_ui_text(prop, "Disable", "Enable/Disable Constraint");
prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_EXPAND);
RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_ui_text(prop, "Expanded", "Constraint's panel is expanded in UI");
RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1);

View File

@ -4922,12 +4922,13 @@ void RNA_def_modifier(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_viewport", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", eModifierMode_Realtime);
RNA_def_property_ui_text(prop, "Realtime", "Display modifier in viewport");
RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
RNA_def_property_flag(prop, PROP_LIB_EXCEPTION | PROP_OVERRIDABLE_STATIC);
RNA_def_property_update(prop, 0, "rna_Modifier_update");
RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 0);
prop = RNA_def_property(srna, "show_render", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", eModifierMode_Render);
RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_ui_text(prop, "Render", "Use modifier during render");
RNA_def_property_ui_icon(prop, ICON_SCENE, 0);
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
@ -4946,6 +4947,7 @@ void RNA_def_modifier(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", eModifierMode_Expanded);
RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_ui_text(prop, "Expanded", "Set modifier expanded in the user interface");
RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1);

View File

@ -2073,6 +2073,7 @@ static void rna_def_object(BlenderRNA *brna)
/* constraints */
prop = RNA_def_property(srna, "constraints", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "Constraint");
RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_ui_text(prop, "Constraints", "Constraints affecting the transformation of the object");
/* RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "constraints__add", "constraints__remove"); */
rna_def_object_constraints(brna, prop);

View File

@ -97,7 +97,7 @@ static void rna_Object_select_set(Object *ob, bContext *C, ReportList *reports,
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
BKE_reportf(reports, RPT_ERROR, "Object '%s' not in Render Layer '%s'!", ob->id.name + 2, view_layer->name);
BKE_reportf(reports, RPT_ERROR, "Object '%s' not in View Layer '%s'!", ob->id.name + 2, view_layer->name);
return;
}

View File

@ -123,6 +123,7 @@ static void rna_Pose_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRN
/* XXX when to use this? ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK); */
DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_POSE, ptr->id.data);
}
static void rna_Pose_IK_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@ -805,6 +806,7 @@ static void rna_def_pose_channel(BlenderRNA *brna)
/* Bone Constraints */
prop = RNA_def_property(srna, "constraints", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "Constraint");
RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_ui_text(prop, "Constraints", "Constraints that act on this PoseChannel");
rna_def_pose_channel_constraints(brna, prop);

View File

@ -1160,14 +1160,6 @@ static int rna_property_override_diff_propptr(
}
}
static char *rna_path_collection_prop_item_extend(const char *rna_path_prop, const char *item_name)
{
const size_t esc_item_name_len = strlen(item_name) * 2;
char *esc_item_name = alloca(sizeof(*esc_item_name) * esc_item_name_len);
BLI_strescape(esc_item_name, item_name, esc_item_name_len);
return BLI_sprintfN("%s[\"%s\"]", rna_path_prop, esc_item_name);
}
int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b,
PropertyRNA *prop_a, PropertyRNA *prop_b,
const int len_a, const int len_b,
@ -1300,7 +1292,6 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b,
case PROP_FLOAT:
{
const bool is_proportional = (prop_a->flag & PROP_PROPORTIONAL) != 0;
if (len_a) {
float array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY];
float *array_a, *array_b;
@ -1320,7 +1311,7 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b,
if (op != NULL && created) {
BKE_override_static_property_operation_get(
op, is_proportional ? IDOVERRIDESTATIC_OP_MULTIPLY : IDOVERRIDESTATIC_OP_REPLACE,
op, IDOVERRIDESTATIC_OP_REPLACE,
NULL, NULL, -1, -1, true, NULL, NULL);
if (r_override_changed) {
*r_override_changed = created;
@ -1347,7 +1338,7 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b,
if (op != NULL && created) { /* If not yet overridden... */
BKE_override_static_property_operation_get(
op, is_proportional ? IDOVERRIDESTATIC_OP_MULTIPLY : IDOVERRIDESTATIC_OP_REPLACE,
op, IDOVERRIDESTATIC_OP_REPLACE,
NULL, NULL, -1, -1, true, NULL, NULL);
if (r_override_changed) {
*r_override_changed = created;
@ -1437,8 +1428,6 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b,
for (; iter_a.valid && iter_b.valid;
RNA_property_collection_next(&iter_a), RNA_property_collection_next(&iter_b), idx++)
{
char *extended_rna_path = NULL;
if (iter_a.ptr.type != iter_b.ptr.type) {
/* nothing we can do (for until we support adding/removing from collections), skip it. */
equals = false;
@ -1459,6 +1448,18 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b,
propname_a = RNA_property_string_get_alloc(&iter_a.ptr, propname, propname_buff_a, sizeof(propname_buff_a), NULL);
propname_b = RNA_property_string_get_alloc(&iter_b.ptr, propname, propname_buff_b, sizeof(propname_buff_b), NULL);
}
#define RNA_PATH_BUFFSIZE 8192
#define RNA_PATH_PRINTF(_str, ...) \
if (BLI_snprintf(extended_rna_path_buffer, RNA_PATH_BUFFSIZE, \
(_str), __VA_ARGS__) >= RNA_PATH_BUFFSIZE) \
{ extended_rna_path = BLI_sprintfN((_str), __VA_ARGS__); }(void)0
#define RNA_PATH_FREE \
if (extended_rna_path != extended_rna_path_buffer) MEM_freeN(extended_rna_path)
char extended_rna_path_buffer[RNA_PATH_BUFFSIZE];
char *extended_rna_path = extended_rna_path_buffer;
/* There may be a propname defined in some cases, while no actual name set
* (e.g. happens with point cache), in that case too we want to fall back to index. */
if ((propname_a != NULL && propname_a[0] != '\0') || (propname_b != NULL && propname_b[0] != '\0')) {
@ -1467,12 +1468,14 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b,
equals = false;
}
else if (rna_path) {
extended_rna_path = rna_path_collection_prop_item_extend(rna_path, propname_a);
char esc_item_name[RNA_PATH_BUFFSIZE];
BLI_strescape(esc_item_name, propname_a, RNA_PATH_BUFFSIZE);
RNA_PATH_PRINTF("%s[\"%s\"]", rna_path, esc_item_name);
}
}
else { /* Based on index... */
if (rna_path) {
extended_rna_path = BLI_sprintfN("%s[%d]", rna_path, idx);
RNA_PATH_PRINTF("%s[%d]", rna_path, idx);
}
}
@ -1490,11 +1493,15 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b,
if (propname_b != propname_buff_b) {
MEM_SAFE_FREE(propname_b);
}
MEM_SAFE_FREE(extended_rna_path);
RNA_PATH_FREE;
if (!rna_path && !equals) {
break; /* Early out in case we do not want to loop over whole collection. */
}
#undef RNA_PATH_BUFFSIZE
#undef RNA_PATH_PRINTF
#undef RNA_PATH_FREE
}
equals = equals && !(iter_a.valid || iter_b.valid); /* Not same number of items in both collections... */

View File

@ -38,22 +38,28 @@
/* We may want to load direct from file. */
PyDoc_STRVAR(bpy_app_icons_new_triangles_doc,
".. function:: new_triangles(coords, colors)"
".. function:: new_triangles(range, coords, colors)"
"\n"
" Create a new icon from triangle geometry.\n"
"\n"
" :arg range: Pair of ints.\n"
" :type range: tuple.\n"
" :arg coords: Sequence of bytes (6 floats for one triangle) for (X, Y) coordinates.\n"
" :type coords: byte sequence\n"
" :type coords: byte sequence.\n"
" :arg colors: Sequence of ints (12 for one triangles) for RGBA.\n"
" :type colors: byte sequence\n"
" :type colors: byte sequence.\n"
" :return: Unique icon value (pass to interface ``icon_value`` argument).\n"
" :rtype: int\n"
);
static PyObject *bpy_app_icons_new_triangles(PyObject *UNUSED(self), PyObject *args)
{
/* bytes */
uchar coords_range[2];
PyObject *py_coords, *py_colors;
if (!PyArg_ParseTuple(args, "SS:new_triangles", &py_coords, &py_colors)) {
if (!PyArg_ParseTuple(
args, "(BB)SS:new_triangles",
&coords_range[0], &coords_range[1], &py_coords, &py_colors))
{
return NULL;
}
@ -78,6 +84,8 @@ static PyObject *bpy_app_icons_new_triangles(PyObject *UNUSED(self), PyObject *a
struct Icon_Geom *geom = MEM_mallocN(sizeof(*geom), __func__);
geom->coords_len = tris_len;
geom->coords_range[0] = coords_range[0];
geom->coords_range[1] = coords_range[1];
geom->coords = coords;
geom->colors = colors;
geom->icon_id = 0;
@ -85,6 +93,36 @@ static PyObject *bpy_app_icons_new_triangles(PyObject *UNUSED(self), PyObject *a
return PyLong_FromLong(icon_id);
}
PyDoc_STRVAR(bpy_app_icons_new_triangles_from_file_doc,
".. function:: new_triangles_from_file(filename)"
"\n"
" Create a new icon from triangle geometry.\n"
"\n"
" :arg range: File path.\n"
" :type range: string.\n"
" :return: Unique icon value (pass to interface ``icon_value`` argument).\n"
" :rtype: int\n"
);
static PyObject *bpy_app_icons_new_triangles_from_file(PyObject *UNUSED(self), PyObject *args)
{
/* bytes */
char *filename;
if (!PyArg_ParseTuple(
args, "s:new_triangles_from_file",
&filename))
{
return NULL;
}
struct Icon_Geom *geom = BKE_icon_geom_from_file(filename);
if (geom == NULL) {
PyErr_SetString(PyExc_ValueError, "Unable to load from file");
return NULL;
}
int icon_id = BKE_icon_geom_ensure(geom);
return PyLong_FromLong(icon_id);
}
PyDoc_STRVAR(bpy_app_icons_release_doc,
".. function:: release(icon_id)"
"\n"
@ -110,6 +148,7 @@ static PyObject *bpy_app_icons_release(PyObject *UNUSED(self), PyObject *args)
static struct PyMethodDef M_AppIcons_methods[] = {
{"new_triangles", (PyCFunction)bpy_app_icons_new_triangles, METH_VARARGS, bpy_app_icons_new_triangles_doc},
{"new_triangles_from_file", (PyCFunction)bpy_app_icons_new_triangles_from_file, METH_VARARGS, bpy_app_icons_new_triangles_from_file_doc},
{"release", (PyCFunction)bpy_app_icons_release, METH_VARARGS, bpy_app_icons_release_doc},
{NULL, NULL, 0, NULL}
};

View File

@ -1953,13 +1953,14 @@ static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHand
int action = WM_HANDLER_CONTINUE;
switch (val) {
case EVT_FILESELECT_FULL_OPEN:
case EVT_FILESELECT_FULL_OPEN:
{
ScrArea *sa;
/* sa can be null when window A is active, but mouse is over window B */
/* in this case, open file select in original window A */
if (handler->op_area == NULL) {
/* sa can be null when window A is active, but mouse is over window B
* in this case, open file select in original window A. Also don't
* use global areas. */
if (handler->op_area == NULL || ED_area_is_global(handler->op_area)) {
bScreen *screen = CTX_wm_screen(C);
sa = (ScrArea *)screen->areabase.first;
}

@ -1 +1 @@
Subproject commit f35d8e55afffb9da50cc13b14615ed280f9e558c
Subproject commit 56f3887596b538a9fc17e0439883f2e2305f2633