Merge branch 'master' into sculpt-dev
This commit is contained in:
commit
193806f590
|
@ -943,10 +943,7 @@ GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type,
|
|||
GHOST_TABLET_DATA_NONE;
|
||||
|
||||
/* Ensure button click occurs at its intended position. */
|
||||
DWORD msgPos = ::GetMessagePos();
|
||||
GHOST_TInt32 x_screen = GET_X_LPARAM(msgPos), y_screen = GET_Y_LPARAM(msgPos);
|
||||
system->pushEvent(new GHOST_EventCursor(
|
||||
system->getMilliSeconds(), GHOST_kEventCursorMove, window, x_screen, y_screen, td));
|
||||
processCursorEvent(window);
|
||||
|
||||
window->updateMouseCapture(type == GHOST_kEventButtonDown ? MousePressed : MouseReleased);
|
||||
return new GHOST_EventButton(system->getMilliSeconds(), type, window, mask, td);
|
||||
|
@ -1106,22 +1103,19 @@ void GHOST_SystemWin32::processPointerEvent(
|
|||
|
||||
GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *window)
|
||||
{
|
||||
if (window->m_tabletInRange) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
|
||||
GHOST_TInt32 x_screen, y_screen;
|
||||
|
||||
system->getCursorPosition(x_screen, y_screen);
|
||||
DWORD msgPos = ::GetMessagePos();
|
||||
GHOST_TInt32 x_screen = GET_X_LPARAM(msgPos);
|
||||
GHOST_TInt32 y_screen = GET_Y_LPARAM(msgPos);
|
||||
GHOST_TInt32 x_accum = 0, y_accum = 0;
|
||||
|
||||
if (window->getCursorGrabModeIsWarp()) {
|
||||
if (window->getCursorGrabModeIsWarp() && !window->m_tabletInRange) {
|
||||
GHOST_TInt32 x_new = x_screen;
|
||||
GHOST_TInt32 y_new = y_screen;
|
||||
GHOST_TInt32 x_accum, y_accum;
|
||||
GHOST_Rect bounds;
|
||||
|
||||
/* fallback to window bounds */
|
||||
/* Fallback to window bounds. */
|
||||
if (window->getCursorGrabBounds(bounds) == GHOST_kFailure) {
|
||||
window->getClientBounds(bounds);
|
||||
}
|
||||
|
@ -1132,29 +1126,19 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
|
|||
|
||||
window->getCursorGrabAccum(x_accum, y_accum);
|
||||
if (x_new != x_screen || y_new != y_screen) {
|
||||
/* when wrapping we don't need to add an event because the
|
||||
* setCursorPosition call will cause a new event after */
|
||||
system->setCursorPosition(x_new, y_new); /* wrap */
|
||||
window->setCursorGrabAccum(x_accum + (x_screen - x_new), y_accum + (y_screen - y_new));
|
||||
}
|
||||
else {
|
||||
return new GHOST_EventCursor(system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
window,
|
||||
x_screen + x_accum,
|
||||
y_screen + y_accum,
|
||||
GHOST_TABLET_DATA_NONE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return new GHOST_EventCursor(system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
window,
|
||||
x_screen,
|
||||
y_screen,
|
||||
GHOST_TABLET_DATA_NONE);
|
||||
}
|
||||
return NULL;
|
||||
|
||||
GHOST_TabletData td = window->m_tabletInRange ? window->getLastTabletData() :
|
||||
GHOST_TABLET_DATA_NONE;
|
||||
return new GHOST_EventCursor(system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
window,
|
||||
x_screen + x_accum,
|
||||
y_screen + y_accum,
|
||||
td);
|
||||
}
|
||||
|
||||
void GHOST_SystemWin32::processWheelEvent(GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam)
|
||||
|
@ -1641,7 +1625,9 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||
window->setWintabOverlap(true);
|
||||
}
|
||||
|
||||
event = processCursorEvent(window);
|
||||
if (!window->m_tabletInRange) {
|
||||
event = processCursorEvent(window);
|
||||
}
|
||||
break;
|
||||
case WM_MOUSEWHEEL: {
|
||||
/* The WM_MOUSEWHEEL message is sent to the focus window
|
||||
|
|
|
@ -75,6 +75,7 @@ bool BKE_object_modifier_gpencil_use_time(struct Object *ob, struct GpencilModif
|
|||
|
||||
bool BKE_object_shaderfx_use_time(struct Object *ob, struct ShaderFxData *md);
|
||||
|
||||
bool BKE_object_supports_modifiers(const struct Object *ob);
|
||||
bool BKE_object_support_modifier_type_check(const struct Object *ob, int modifier_type);
|
||||
|
||||
/* Active modifier. */
|
||||
|
|
|
@ -1315,6 +1315,15 @@ ModifierData *BKE_object_active_modifier(const Object *ob)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return True if the object's type supports regular modifiers (not grease pencil modifiers).
|
||||
*/
|
||||
bool BKE_object_supports_modifiers(const Object *ob)
|
||||
{
|
||||
return (
|
||||
ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE, OB_POINTCLOUD, OB_VOLUME));
|
||||
}
|
||||
|
||||
bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type)
|
||||
{
|
||||
const ModifierTypeInfo *mti = BKE_modifier_get_info(modifier_type);
|
||||
|
@ -1377,6 +1386,7 @@ bool BKE_object_copy_modifier(struct Object *ob_dst, const struct Object *ob_src
|
|||
BKE_modifier_copydata(md, nmd);
|
||||
BLI_addtail(&ob_dst->modifiers, nmd);
|
||||
BKE_modifier_unique_name(&ob_dst->modifiers, nmd);
|
||||
BKE_object_modifier_set_active(ob_dst, nmd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
#include "BKE_material.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_particle.h"
|
||||
#include "BKE_pointcache.h"
|
||||
#include "BKE_scene.h"
|
||||
|
@ -3948,6 +3949,7 @@ static ModifierData *object_add_or_copy_particle_system(
|
|||
psmd = (ParticleSystemModifierData *)md;
|
||||
psmd->psys = psys;
|
||||
BLI_addtail(&ob->modifiers, md);
|
||||
BKE_object_modifier_set_active(ob, md);
|
||||
|
||||
psys->totpart = 0;
|
||||
psys->flag = PSYS_CURRENT;
|
||||
|
|
|
@ -835,3 +835,99 @@ void OBJECT_OT_gpencil_modifier_copy(wmOperatorType *ot)
|
|||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
|
||||
gpencil_edit_modifier_properties(ot);
|
||||
}
|
||||
|
||||
/************************ Copy Modifier to Selected Operator *********************/
|
||||
|
||||
static int gpencil_modifier_copy_to_selected_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *obact = ED_object_active_context(C);
|
||||
GpencilModifierData *md = gpencil_edit_modifier_property_get(op, obact, 0);
|
||||
|
||||
if (!md) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (obact->type != OB_GPENCIL) {
|
||||
BKE_reportf(op->reports,
|
||||
RPT_ERROR,
|
||||
"Source object '%s' is not a grease pencil object",
|
||||
obact->id.name + 2);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
|
||||
if (ob == obact) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ob->type != OB_GPENCIL) {
|
||||
BKE_reportf(op->reports,
|
||||
RPT_WARNING,
|
||||
"Destination object '%s' is not a grease pencil object",
|
||||
ob->id.name + 2);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This always returns true right now. */
|
||||
BKE_object_copy_gpencil_modifier(ob, md);
|
||||
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
|
||||
}
|
||||
CTX_DATA_END;
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int gpencil_modifier_copy_to_selected_invoke(bContext *C,
|
||||
wmOperator *op,
|
||||
const wmEvent *event)
|
||||
{
|
||||
int retval;
|
||||
if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) {
|
||||
return gpencil_modifier_copy_to_selected_exec(C, op);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool gpencil_modifier_copy_to_selected_poll(bContext *C)
|
||||
{
|
||||
Object *obact = ED_object_active_context(C);
|
||||
|
||||
/* This could have a performance impact in the worst case, where there are many objects selected
|
||||
* and none of them pass the check. But that should be uncommon, and this operator is only
|
||||
* exposed in a drop-down menu anyway. */
|
||||
bool found_supported_objects = false;
|
||||
CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
|
||||
if (ob == obact) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ob->type == OB_GPENCIL) {
|
||||
found_supported_objects = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CTX_DATA_END;
|
||||
|
||||
if (!found_supported_objects) {
|
||||
CTX_wm_operator_poll_msg_set(C, "No supported objects were selected");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void OBJECT_OT_gpencil_modifier_copy_to_selected(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Copy Modifier to Selected";
|
||||
ot->description = "Copy the modifier from the active object to all selected objects";
|
||||
ot->idname = "OBJECT_OT_gpencil_modifier_copy_to_selected";
|
||||
|
||||
ot->invoke = gpencil_modifier_copy_to_selected_invoke;
|
||||
ot->exec = gpencil_modifier_copy_to_selected_exec;
|
||||
ot->poll = gpencil_modifier_copy_to_selected_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
|
||||
gpencil_edit_modifier_properties(ot);
|
||||
}
|
||||
|
|
|
@ -175,6 +175,7 @@ void OBJECT_OT_modifier_apply(struct wmOperatorType *ot);
|
|||
void OBJECT_OT_modifier_apply_as_shapekey(wmOperatorType *ot);
|
||||
void OBJECT_OT_modifier_convert(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_modifier_copy(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_modifier_copy_to_selected(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_modifier_set_active(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_multires_subdivide(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_multires_reshape(struct wmOperatorType *ot);
|
||||
|
@ -203,6 +204,7 @@ void OBJECT_OT_gpencil_modifier_move_down(struct wmOperatorType *ot);
|
|||
void OBJECT_OT_gpencil_modifier_move_to_index(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_gpencil_modifier_apply(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_gpencil_modifier_copy(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_gpencil_modifier_copy_to_selected(struct wmOperatorType *ot);
|
||||
|
||||
/* object_shader_fx.c */
|
||||
void OBJECT_OT_shaderfx_add(struct wmOperatorType *ot);
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#include "DNA_anim_types.h"
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_curve_types.h"
|
||||
#include "DNA_dynamicpaint_types.h"
|
||||
#include "DNA_fluid_types.h"
|
||||
#include "DNA_key_types.h"
|
||||
#include "DNA_lattice_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
|
@ -1681,6 +1683,229 @@ void OBJECT_OT_modifier_set_active(wmOperatorType *ot)
|
|||
edit_modifier_properties(ot);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
/** \name Copy Modifier To Selected Operator
|
||||
* \{ */
|
||||
|
||||
/* If the modifier uses particles, copy particle system to destination object
|
||||
* or reuse existing if it has the same ParticleSettings */
|
||||
static void copy_or_reuse_particle_system(bContext *C, Object *ob, ModifierData *md)
|
||||
{
|
||||
ParticleSystem *psys_on_modifier = NULL;
|
||||
|
||||
if (md->type == eModifierType_DynamicPaint) {
|
||||
DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
|
||||
if (pmd->brush && pmd->brush->psys) {
|
||||
psys_on_modifier = pmd->brush->psys;
|
||||
}
|
||||
}
|
||||
else if (md->type == eModifierType_Fluid) {
|
||||
FluidModifierData *fmd = (FluidModifierData *)md;
|
||||
if (fmd->type == MOD_FLUID_TYPE_FLOW) {
|
||||
if (fmd->flow && fmd->flow->psys) {
|
||||
psys_on_modifier = fmd->flow->psys;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!psys_on_modifier) {
|
||||
return;
|
||||
}
|
||||
|
||||
ParticleSystem *psys_on_new_modifier = NULL;
|
||||
|
||||
/* Check if a particle system with the same particle settings
|
||||
* already exists on the destination object. */
|
||||
LISTBASE_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
|
||||
if (psys_on_modifier->part == psys->part) {
|
||||
psys_on_new_modifier = psys;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If it does not exist, copy the particle system to the destination object. */
|
||||
if (!psys_on_new_modifier) {
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
object_copy_particle_system(bmain, scene, ob, psys_on_modifier);
|
||||
|
||||
LISTBASE_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
|
||||
if (psys_on_modifier->part == psys->part) {
|
||||
psys_on_new_modifier = psys;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the modifier to point to the new/existing particle system. */
|
||||
LISTBASE_FOREACH (ModifierData *, new_md, &ob->modifiers) {
|
||||
if (new_md->type == eModifierType_DynamicPaint) {
|
||||
DynamicPaintModifierData *new_pmd = (DynamicPaintModifierData *)new_md;
|
||||
|
||||
if (psys_on_modifier == new_pmd->brush->psys) {
|
||||
new_pmd->brush->psys = psys_on_new_modifier;
|
||||
}
|
||||
}
|
||||
else if (new_md->type == eModifierType_Fluid) {
|
||||
FluidModifierData *new_fmd = (FluidModifierData *)new_md;
|
||||
|
||||
if (psys_on_modifier == new_fmd->flow->psys) {
|
||||
new_fmd->flow->psys = psys_on_new_modifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int modifier_copy_to_selected_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *obact = ED_object_active_context(C);
|
||||
ModifierData *md = edit_modifier_property_get(op, obact, 0);
|
||||
|
||||
if (!md) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
int num_copied = 0;
|
||||
const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
|
||||
|
||||
CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
|
||||
if (ob == obact) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Checked in #BKE_object_copy_modifier, but check here too so we can give a better message. */
|
||||
if (!BKE_object_support_modifier_type_check(ob, md->type)) {
|
||||
BKE_reportf(op->reports,
|
||||
RPT_WARNING,
|
||||
"Object '%s' does not support %s modifiers",
|
||||
ob->id.name + 2,
|
||||
mti->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mti->flags & eModifierTypeFlag_Single) {
|
||||
if (BKE_modifiers_findby_type(ob, md->type)) {
|
||||
BKE_reportf(op->reports,
|
||||
RPT_WARNING,
|
||||
"Modifier can only be added once to object '%s'",
|
||||
ob->id.name + 2);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (md->type == eModifierType_ParticleSystem) {
|
||||
ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
|
||||
object_copy_particle_system(bmain, scene, ob, psmd->psys);
|
||||
}
|
||||
else {
|
||||
if (!BKE_object_copy_modifier(ob, obact, md)) {
|
||||
BKE_reportf(op->reports,
|
||||
RPT_ERROR,
|
||||
"Copying modifier '%s' to object '%s' failed",
|
||||
md->name,
|
||||
ob->id.name + 2);
|
||||
}
|
||||
}
|
||||
|
||||
if (ELEM(md->type, eModifierType_DynamicPaint, eModifierType_Fluid)) {
|
||||
copy_or_reuse_particle_system(C, ob, md);
|
||||
}
|
||||
|
||||
num_copied++;
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
|
||||
}
|
||||
CTX_DATA_END;
|
||||
|
||||
if (num_copied > 0) {
|
||||
DEG_relations_tag_update(bmain);
|
||||
}
|
||||
else {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "Modifier '%s' was not copied to any objects", md->name);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int modifier_copy_to_selected_invoke(bContext *C,
|
||||
wmOperator *op,
|
||||
const wmEvent *UNUSED(event))
|
||||
{
|
||||
if (edit_modifier_invoke_properties(C, op)) {
|
||||
return modifier_copy_to_selected_exec(C, op);
|
||||
}
|
||||
/* Work around multiple operators using the same shortcut. */
|
||||
return (OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED);
|
||||
}
|
||||
|
||||
static bool modifier_copy_to_selected_poll(bContext *C)
|
||||
{
|
||||
PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
|
||||
Object *obact = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C);
|
||||
ModifierData *md = ptr.data;
|
||||
|
||||
/* This just mirrors the check in #BKE_object_copy_modifier,
|
||||
* but there is no reasoning for it there. */
|
||||
if (md && ELEM(md->type, eModifierType_Hook, eModifierType_Collision)) {
|
||||
CTX_wm_operator_poll_msg_set(C, "Not supported for \"Collision\" or \"Hook\" modifiers");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!obact) {
|
||||
CTX_wm_operator_poll_msg_set(C, "No selected object is active");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!BKE_object_supports_modifiers(obact)) {
|
||||
CTX_wm_operator_poll_msg_set(C, "Object type of source object is not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This could have a performance impact in the worst case, where there are many objects selected
|
||||
* and none of them pass either of the checks. But that should be uncommon, and this operator is
|
||||
* only exposed in a drop-down menu anyway. */
|
||||
bool found_supported_objects = false;
|
||||
CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
|
||||
if (ob == obact) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!md && BKE_object_supports_modifiers(ob)) {
|
||||
/* Skip type check if modifier could not be found ("modifier" context variable not set). */
|
||||
found_supported_objects = true;
|
||||
break;
|
||||
}
|
||||
else if (BKE_object_support_modifier_type_check(ob, md->type)) {
|
||||
found_supported_objects = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CTX_DATA_END;
|
||||
|
||||
if (!found_supported_objects) {
|
||||
CTX_wm_operator_poll_msg_set(C, "No supported objects were selected");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void OBJECT_OT_modifier_copy_to_selected(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Copy Modifier to Selected";
|
||||
ot->description = "Copy the modifier from the active object to all selected objects";
|
||||
ot->idname = "OBJECT_OT_modifier_copy_to_selected";
|
||||
|
||||
ot->invoke = modifier_copy_to_selected_invoke;
|
||||
ot->exec = modifier_copy_to_selected_exec;
|
||||
ot->poll = modifier_copy_to_selected_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
|
||||
edit_modifier_properties(ot);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
|
|
@ -137,6 +137,7 @@ void ED_operatortypes_object(void)
|
|||
WM_operatortype_append(OBJECT_OT_modifier_apply_as_shapekey);
|
||||
WM_operatortype_append(OBJECT_OT_modifier_convert);
|
||||
WM_operatortype_append(OBJECT_OT_modifier_copy);
|
||||
WM_operatortype_append(OBJECT_OT_modifier_copy_to_selected);
|
||||
WM_operatortype_append(OBJECT_OT_modifier_set_active);
|
||||
WM_operatortype_append(OBJECT_OT_multires_subdivide);
|
||||
WM_operatortype_append(OBJECT_OT_multires_reshape);
|
||||
|
@ -159,6 +160,7 @@ void ED_operatortypes_object(void)
|
|||
WM_operatortype_append(OBJECT_OT_gpencil_modifier_move_to_index);
|
||||
WM_operatortype_append(OBJECT_OT_gpencil_modifier_apply);
|
||||
WM_operatortype_append(OBJECT_OT_gpencil_modifier_copy);
|
||||
WM_operatortype_append(OBJECT_OT_gpencil_modifier_copy_to_selected);
|
||||
|
||||
/* shader fx */
|
||||
WM_operatortype_append(OBJECT_OT_shaderfx_add);
|
||||
|
|
|
@ -956,16 +956,14 @@ float ED_view3d_grid_view_scale(Scene *scene,
|
|||
RegionView3D *rv3d = region->regiondata;
|
||||
if (!rv3d->is_persp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
|
||||
/* Decrease the distance between grid snap points depending on zoom. */
|
||||
/* `0.38` was a value visually obtained in order to get a snap distance
|
||||
* that matches previous versions Blender.*/
|
||||
float min_dist = 16.0f / (region->sizex * rv3d->winmat[0][0]);
|
||||
float dist = 12.0f / (region->sizex * rv3d->winmat[0][0]);
|
||||
float grid_steps[STEPS_LEN];
|
||||
ED_view3d_grid_steps(scene, v3d, rv3d, grid_steps);
|
||||
/* Skip last item, in case the 'mid_dist' is greater than the largest unit. */
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(grid_steps) - 1; i++) {
|
||||
grid_scale = grid_steps[i];
|
||||
if (grid_scale > min_dist) {
|
||||
if (grid_scale > dist) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,7 +85,8 @@ bool transdata_check_local_islands(TransInfo *t, short around)
|
|||
|
||||
void setTransformViewMatrices(TransInfo *t)
|
||||
{
|
||||
if (t->spacetype == SPACE_VIEW3D && t->region && t->region->regiontype == RGN_TYPE_WINDOW) {
|
||||
if (!(t->options & CTX_PAINT_CURVE) && (t->spacetype == SPACE_VIEW3D) && t->region &&
|
||||
(t->region->regiontype == RGN_TYPE_WINDOW)) {
|
||||
RegionView3D *rv3d = t->region->regiondata;
|
||||
|
||||
copy_m4_m4(t->viewmat, rv3d->viewmat);
|
||||
|
|
|
@ -1298,6 +1298,11 @@ static void gizmo_xform_message_subscribe(wmGizmoGroup *gzgroup,
|
|||
void drawDial3d(const TransInfo *t)
|
||||
{
|
||||
if (t->mode == TFM_ROTATION && t->spacetype == SPACE_VIEW3D) {
|
||||
if (t->options & CTX_PAINT_CURVE) {
|
||||
/* Matrices are in the screen space. Not supported. */
|
||||
return;
|
||||
}
|
||||
|
||||
wmGizmo *gz = wm_gizmomap_modal_get(t->region->gizmo_map);
|
||||
if (gz == NULL) {
|
||||
/* We only draw Dial3d if the operator has been called by a gizmo. */
|
||||
|
|
|
@ -602,20 +602,34 @@ short transform_orientation_matrix_get(
|
|||
orientation = V3D_ORIENT_CUSTOM;
|
||||
}
|
||||
|
||||
if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
|
||||
if ((t->spacetype == SPACE_VIEW3D) && t->region && (t->region->regiontype == RGN_TYPE_WINDOW)) {
|
||||
rv3d = t->region->regiondata;
|
||||
}
|
||||
|
||||
return ED_transform_calc_orientation_from_type_ex(C,
|
||||
r_spacemtx,
|
||||
/* extra args (can be accessed from context) */
|
||||
scene,
|
||||
rv3d,
|
||||
ob,
|
||||
obedit,
|
||||
orientation,
|
||||
orientation_index_custom,
|
||||
t->around);
|
||||
short orient_type = ED_transform_calc_orientation_from_type_ex(
|
||||
C,
|
||||
r_spacemtx,
|
||||
/* extra args (can be accessed from context) */
|
||||
scene,
|
||||
rv3d,
|
||||
ob,
|
||||
obedit,
|
||||
orientation,
|
||||
orientation_index_custom,
|
||||
t->around);
|
||||
|
||||
if (rv3d && (t->options & CTX_PAINT_CURVE)) {
|
||||
/* Screen space in the 3d region. */
|
||||
if (orient_type == V3D_ORIENT_VIEW) {
|
||||
unit_m3(r_spacemtx);
|
||||
}
|
||||
else {
|
||||
mul_m3_m4m3(r_spacemtx, rv3d->viewmat, r_spacemtx);
|
||||
normalize_m3(r_spacemtx);
|
||||
}
|
||||
}
|
||||
|
||||
return orient_type;
|
||||
}
|
||||
|
||||
const char *transform_orientations_spacename_get(TransInfo *t, const short orient_type)
|
||||
|
|
|
@ -270,6 +270,11 @@ static void gpencil_modifier_ops_extra_draw(bContext *C, uiLayout *layout, void
|
|||
ICON_DUPLICATE,
|
||||
"OBJECT_OT_gpencil_modifier_copy");
|
||||
|
||||
uiItemO(layout,
|
||||
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy to Selected"),
|
||||
0,
|
||||
"OBJECT_OT_gpencil_modifier_copy_to_selected");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
/* Move to first. */
|
||||
|
|
|
@ -5696,8 +5696,7 @@ static char *rna_idp_path(PointerRNA *ptr,
|
|||
BLI_assert(haystack->type == IDP_GROUP);
|
||||
|
||||
link.up = parent_link;
|
||||
/* always set both name and index,
|
||||
* else a stale value might get used */
|
||||
/* Always set both name and index, else a stale value might get used. */
|
||||
link.name = NULL;
|
||||
link.index = -1;
|
||||
|
||||
|
@ -5708,11 +5707,30 @@ static char *rna_idp_path(PointerRNA *ptr,
|
|||
path = rna_idp_path_create(&link);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Early out in case the IDProperty type cannot contain RNA properties. */
|
||||
if (!ELEM(iter->type, IDP_GROUP, IDP_IDPARRAY)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Ensure this is RNA. */
|
||||
/* NOTE: `iter` might be a fully user-defined IDProperty (a.k.a. custom data), which name
|
||||
* collides with an actual fully static RNA property of the same struct (which would then not
|
||||
* be flagged with `PROP_IDPROPERTY`).
|
||||
*
|
||||
* That case must be ignored here, we only want to deal with runtime RNA properties stored in
|
||||
* IDProps.
|
||||
*
|
||||
* See T84091. */
|
||||
PropertyRNA *prop = RNA_struct_find_property(ptr, iter->name);
|
||||
if (prop == NULL || (prop->flag & PROP_IDPROPERTY) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (iter->type == IDP_GROUP) {
|
||||
/* ensure this is RNA */
|
||||
PropertyRNA *prop = RNA_struct_find_property(ptr, iter->name);
|
||||
if (prop && prop->type == PROP_POINTER) {
|
||||
if (prop->type == PROP_POINTER) {
|
||||
PointerRNA child_ptr = RNA_property_pointer_get(ptr, prop);
|
||||
BLI_assert(child_ptr.type != NULL);
|
||||
link.name = iter->name;
|
||||
link.index = -1;
|
||||
if ((path = rna_idp_path(&child_ptr, iter, needle, &link))) {
|
||||
|
@ -5721,8 +5739,7 @@ static char *rna_idp_path(PointerRNA *ptr,
|
|||
}
|
||||
}
|
||||
else if (iter->type == IDP_IDPARRAY) {
|
||||
PropertyRNA *prop = RNA_struct_find_property(ptr, iter->name);
|
||||
if (prop && prop->type == PROP_COLLECTION) {
|
||||
if (prop->type == PROP_COLLECTION) {
|
||||
IDProperty *array = IDP_IDPArray(iter);
|
||||
if (needle >= array && needle < (iter->len + array)) { /* found! */
|
||||
link.name = iter->name;
|
||||
|
@ -5735,6 +5752,7 @@ static char *rna_idp_path(PointerRNA *ptr,
|
|||
for (j = 0; j < iter->len; j++, array++) {
|
||||
PointerRNA child_ptr;
|
||||
if (RNA_property_collection_lookup_int(ptr, prop, j, &child_ptr)) {
|
||||
BLI_assert(child_ptr.type != NULL);
|
||||
link.index = j;
|
||||
if ((path = rna_idp_path(&child_ptr, array, needle, &link))) {
|
||||
break;
|
||||
|
@ -5752,7 +5770,10 @@ static char *rna_idp_path(PointerRNA *ptr,
|
|||
}
|
||||
|
||||
/**
|
||||
* Find the path from the structure referenced by the pointer to the #IDProperty object.
|
||||
* Find the path from the structure referenced by the pointer to the runtime RNA-defined
|
||||
* #IDProperty object.
|
||||
*
|
||||
* \note Does *not* handle pure user-defined IDProperties (a.k.a. custom properties).
|
||||
*
|
||||
* \param ptr: Reference to the object owning the custom property storage.
|
||||
* \param needle: Custom property object to find.
|
||||
|
|
|
@ -256,6 +256,11 @@ static void modifier_ops_extra_draw(bContext *C, uiLayout *layout, void *md_v)
|
|||
"OBJECT_OT_modifier_copy");
|
||||
}
|
||||
|
||||
uiItemO(layout,
|
||||
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy to Selected"),
|
||||
0,
|
||||
"OBJECT_OT_modifier_copy_to_selected");
|
||||
|
||||
uiItemS(layout);
|
||||
|
||||
/* Move to first. */
|
||||
|
|
Loading…
Reference in New Issue