Merge branch 'master' into greasepencil-object

This commit is contained in:
2019-11-22 17:41:05 +01:00
53 changed files with 843 additions and 333 deletions

View File

@@ -163,9 +163,8 @@ CPU:=$(shell uname -m)
BLENDER_DIR:=$(shell pwd -P)
BUILD_TYPE:=Release
ifndef BUILD_CMAKE_ARGS
BUILD_CMAKE_ARGS:=
endif
# CMake arguments, assigned to local variable to make it mutable.
CMAKE_CONFIG_ARGS := $(BUILD_CMAKE_ARGS)
ifndef BUILD_DIR
BUILD_DIR:=$(shell dirname "$(BLENDER_DIR)")/build_$(OS_NCASE)
@@ -213,34 +212,34 @@ ifneq "$(findstring debug, $(MAKECMDGOALS))" ""
endif
ifneq "$(findstring full, $(MAKECMDGOALS))" ""
BUILD_DIR:=$(BUILD_DIR)_full
BUILD_CMAKE_ARGS:=$(BUILD_CMAKE_ARGS) -C"$(BLENDER_DIR)/build_files/cmake/config/blender_full.cmake"
CMAKE_CONFIG_ARGS:=-C"$(BLENDER_DIR)/build_files/cmake/config/blender_full.cmake" $(CMAKE_CONFIG_ARGS)
endif
ifneq "$(findstring lite, $(MAKECMDGOALS))" ""
BUILD_DIR:=$(BUILD_DIR)_lite
BUILD_CMAKE_ARGS:=$(BUILD_CMAKE_ARGS) -C"$(BLENDER_DIR)/build_files/cmake/config/blender_lite.cmake"
CMAKE_CONFIG_ARGS:=-C"$(BLENDER_DIR)/build_files/cmake/config/blender_lite.cmake" $(CMAKE_CONFIG_ARGS)
endif
ifneq "$(findstring cycles, $(MAKECMDGOALS))" ""
BUILD_DIR:=$(BUILD_DIR)_cycles
BUILD_CMAKE_ARGS:=$(BUILD_CMAKE_ARGS) -C"$(BLENDER_DIR)/build_files/cmake/config/cycles_standalone.cmake"
CMAKE_CONFIG_ARGS:=-C"$(BLENDER_DIR)/build_files/cmake/config/cycles_standalone.cmake" $(CMAKE_CONFIG_ARGS)
endif
ifneq "$(findstring headless, $(MAKECMDGOALS))" ""
BUILD_DIR:=$(BUILD_DIR)_headless
BUILD_CMAKE_ARGS:=$(BUILD_CMAKE_ARGS) -C"$(BLENDER_DIR)/build_files/cmake/config/blender_headless.cmake"
CMAKE_CONFIG_ARGS:=-C"$(BLENDER_DIR)/build_files/cmake/config/blender_headless.cmake" $(CMAKE_CONFIG_ARGS)
endif
ifneq "$(findstring bpy, $(MAKECMDGOALS))" ""
BUILD_DIR:=$(BUILD_DIR)_bpy
BUILD_CMAKE_ARGS:=$(BUILD_CMAKE_ARGS) -C"$(BLENDER_DIR)/build_files/cmake/config/bpy_module.cmake"
CMAKE_CONFIG_ARGS:=-C"$(BLENDER_DIR)/build_files/cmake/config/bpy_module.cmake" $(CMAKE_CONFIG_ARGS)
endif
ifneq "$(findstring developer, $(MAKECMDGOALS))" ""
BUILD_CMAKE_ARGS:=$(BUILD_CMAKE_ARGS) -C"$(BLENDER_DIR)/build_files/cmake/config/blender_developer.cmake"
CMAKE_CONFIG_ARGS:=-C"$(BLENDER_DIR)/build_files/cmake/config/blender_developer.cmake" $(CMAKE_CONFIG_ARGS)
endif
# -----------------------------------------------------------------------------
# build tool
ifneq "$(findstring ninja, $(MAKECMDGOALS))" ""
BUILD_CMAKE_ARGS:=$(BUILD_CMAKE_ARGS) -G Ninja
CMAKE_CONFIG_ARGS:=$(CMAKE_CONFIG_ARGS) -G Ninja
BUILD_COMMAND:=ninja
DEPS_BUILD_COMMAND:=ninja
else
@@ -288,7 +287,7 @@ endif
# -----------------------------------------------------------------------------
# Macro for configuring cmake
CMAKE_CONFIG = cmake $(BUILD_CMAKE_ARGS) \
CMAKE_CONFIG = cmake $(CMAKE_CONFIG_ARGS) \
-H"$(BLENDER_DIR)" \
-B"$(BUILD_DIR)" \
-DCMAKE_BUILD_TYPE_INIT:STRING=$(BUILD_TYPE)

View File

@@ -292,8 +292,8 @@ int FFMPEGReader::read_packet(void* opaque, uint8_t* buf, int buf_size)
{
FFMPEGReader* reader = reinterpret_cast<FFMPEGReader*>(opaque);
int64_t remaining_buffer_size = reader->m_membuffer->getSize() - reader->m_membufferpos;
int64_t size = std::min(static_cast<int64_t>(buf_size), remaining_buffer_size);
int size = std::min(buf_size, reader->m_membuffer->getSize() - reader->m_membufferpos);
if(size < 0)
return -1;
@@ -319,7 +319,14 @@ int64_t FFMPEGReader::seek_packet(void* opaque, int64_t offset, int whence)
return reader->m_membuffer->getSize();
}
return (reader->m_membufferpos += offset);
int64_t position = reader->m_membufferpos + offset;
if(position > reader->m_membuffer->getSize())
position = reader->m_membuffer->getSize();
reader->m_membufferpos = int(position);
return position;
}
bool FFMPEGReader::isSeekable() const

View File

@@ -112,7 +112,7 @@ private:
/**
* Reading position of the buffer.
*/
int64_t m_membufferpos;
int m_membufferpos;
/**
* Whether the audio data has to be interleaved after reading.

View File

@@ -2,4 +2,6 @@ Project: WC Width
URL: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
License: ICS
Upstream version: 2007-05-26
Local modifications: None
Local modifications:
* Fix T33192
Bad encoding of utf-8 on windows systems.

View File

@@ -59,8 +59,6 @@
* Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
*/
#include <wchar.h>
#include "wcwidth.h"
struct interval {
@@ -69,7 +67,7 @@ struct interval {
};
/* auxiliary function for binary search in interval table */
static int bisearch(wchar_t ucs, const struct interval *table, int max) {
static int bisearch(char32_t ucs, const struct interval *table, int max) {
int min = 0;
int mid;
@@ -121,7 +119,7 @@ static int bisearch(wchar_t ucs, const struct interval *table, int max) {
* in ISO 10646.
*/
int mk_wcwidth(wchar_t ucs)
int mk_wcwidth(char32_t ucs)
{
/* sorted list of non-overlapping intervals of non-spacing characters */
/* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
@@ -206,7 +204,7 @@ int mk_wcwidth(wchar_t ucs)
}
int mk_wcswidth(const wchar_t *pwcs, size_t n)
int mk_wcswidth(const char32_t *pwcs, size_t n)
{
int w, width = 0;
@@ -229,7 +227,7 @@ int mk_wcswidth(const wchar_t *pwcs, size_t n)
* the traditional terminal character-width behaviour. It is not
* otherwise recommended for general use.
*/
int mk_wcwidth_cjk(wchar_t ucs)
int mk_wcwidth_cjk(char32_t ucs)
{
/* sorted list of non-overlapping intervals of East Asian Ambiguous
* characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
@@ -297,7 +295,7 @@ int mk_wcwidth_cjk(wchar_t ucs)
}
int mk_wcswidth_cjk(const wchar_t *pwcs, size_t n)
int mk_wcswidth_cjk(const char32_t *pwcs, size_t n)
{
int w, width = 0;

View File

@@ -20,11 +20,19 @@
#ifndef __WCWIDTH_H__
#define __WCWIDTH_H__
#include <wchar.h>
#ifndef __cplusplus
# if defined(__APPLE__)
/* The <uchar.h> standard header is missing on macOS. */
#include <stddef.h>
typedef unsigned int char32_t;
# else
# include <uchar.h>
# endif
#endif
int mk_wcwidth(wchar_t ucs);
int mk_wcswidth(const wchar_t *pwcs, size_t n);
int mk_wcwidth_cjk(wchar_t ucs);
int mk_wcswidth_cjk(const wchar_t *pwcs, size_t n);
int mk_wcwidth(char32_t ucs);
int mk_wcswidth(const char32_t *pwcs, size_t n);
int mk_wcwidth_cjk(char32_t ucs);
int mk_wcswidth_cjk(const char32_t *pwcs, size_t n);
#endif

View File

@@ -44,7 +44,7 @@ template<bool always = false> ccl_device_forceinline uint get_object_id()
#endif
// Choose between always returning object ID or only for instances
if (always)
// Can just remove the high bit since instace always contains object ID
// Can just remove the high bit since instance always contains object ID
return object & 0x7FFFFF;
// Set to OBJECT_NONE if this is not an instanced object
else if (object & 0x800000)
@@ -263,8 +263,12 @@ extern "C" __global__ void __intersection__curve()
const uint type = kernel_tex_fetch(__prim_type, prim);
const uint visibility = optixGetPayload_4();
const float3 P = optixGetObjectRayOrigin();
const float3 dir = optixGetObjectRayDirection();
float3 P = optixGetObjectRayOrigin();
float3 dir = optixGetObjectRayDirection();
// The direction is not normalized by default, but the curve intersection routine expects that
float len;
dir = normalize_len(dir, &len);
# ifdef __OBJECT_MOTION__
const float time = optixGetRayTime();
@@ -274,11 +278,14 @@ extern "C" __global__ void __intersection__curve()
Intersection isect;
isect.t = optixGetRayTmax();
// Transform maximum distance into object space
if (isect.t != FLT_MAX)
isect.t *= len;
if (!(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) ?
curve_intersect(NULL, &isect, P, dir, visibility, object, prim, time, type) :
cardinal_curve_intersect(NULL, &isect, P, dir, visibility, object, prim, time, type)) {
optixReportIntersection(isect.t,
optixReportIntersection(isect.t / len,
type & PRIMITIVE_ALL,
__float_as_int(isect.u), // Attribute_0
__float_as_int(isect.v)); // Attribute_1

View File

@@ -1411,13 +1411,9 @@ def km_graph_editor(params):
{"properties": [("mode", 'RIGHT'), ("extend", False)]}),
*_template_items_select_actions(params, "graph.select_all"),
("graph.select_box", {"type": 'B', "value": 'PRESS'},
{"properties": [("axis_range", False), ("include_handles", False)]}),
{"properties": [("axis_range", False)]}),
("graph.select_box", {"type": 'B', "value": 'PRESS', "alt": True},
{"properties": [("axis_range", True), ("include_handles", False)]}),
("graph.select_box", {"type": 'B', "value": 'PRESS', "ctrl": True},
{"properties": [("axis_range", False), ("include_handles", True)]}),
("graph.select_box", {"type": 'B', "value": 'PRESS', "ctrl": True, "alt": True},
{"properties": [("axis_range", True), ("include_handles", True)]}),
{"properties": [("axis_range", True)]}),
("graph.select_box", {"type": params.select_tweak, "value": 'ANY'},
{"properties": [("tweak", True), ("mode", 'SET')]}),
("graph.select_box", {"type": params.select_tweak, "value": 'ANY', "shift": True},
@@ -2225,7 +2221,7 @@ def km_text(params):
{"properties": [("direction", 'UP')]}),
("text.move_lines", {"type": 'DOWN_ARROW', "value": 'PRESS', "shift": True, "ctrl": True},
{"properties": [("direction", 'DOWN')]}),
("text.indent", {"type": 'TAB', "value": 'PRESS'}, None),
("text.indent_or_autocomplete", {"type": 'TAB', "value": 'PRESS'}, None),
("text.unindent", {"type": 'TAB', "value": 'PRESS', "shift": True}, None),
("text.comment_toggle", {"type": 'SLASH', "value": 'PRESS', "ctrl": True}, None),
("text.move", {"type": 'HOME', "value": 'PRESS'},
@@ -2305,7 +2301,6 @@ def km_text(params):
{"properties": [("lines", 1)]}),
("text.line_break", {"type": 'RET', "value": 'PRESS'}, None),
("text.line_break", {"type": 'NUMPAD_ENTER', "value": 'PRESS'}, None),
("text.autocomplete", {"type": 'SPACE', "value": 'PRESS', "ctrl": True}, None),
("text.line_number", {"type": 'TEXTINPUT', "value": 'ANY', "any": True}, None),
op_menu("TEXT_MT_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}),
("text.insert", {"type": 'TEXTINPUT', "value": 'ANY', "any": True}, None),
@@ -2535,7 +2530,6 @@ def km_console(params):
{"properties": [("interactive", True)]}),
("console.execute", {"type": 'NUMPAD_ENTER', "value": 'PRESS'},
{"properties": [("interactive", True)]}),
("console.autocomplete", {"type": 'SPACE', "value": 'PRESS', "ctrl": True}, None),
("console.copy_as_script", {"type": 'C', "value": 'PRESS', "shift": True, "ctrl": True}, None),
("console.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
("console.paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
@@ -2543,7 +2537,7 @@ def km_console(params):
("console.select_word", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'}, None),
("console.insert", {"type": 'TAB', "value": 'PRESS', "ctrl": True},
{"properties": [("text", '\t')]}),
("console.indent", {"type": 'TAB', "value": 'PRESS'}, None),
("console.indent_or_autocomplete", {"type": 'TAB', "value": 'PRESS'}, None),
("console.unindent", {"type": 'TAB', "value": 'PRESS', "shift": True}, None),
op_menu("CONSOLE_MT_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}),
("console.insert", {"type": 'TEXTINPUT', "value": 'ANY', "any": True}, None),

View File

@@ -860,19 +860,15 @@ def km_graph_editor(params):
("graph.select_all", {"type": 'A', "value": 'PRESS', "ctrl": True, "shift": True}, {"properties": [("action", 'DESELECT')]}),
("graph.select_all", {"type": 'I', "value": 'PRESS', "ctrl": True}, {"properties": [("action", 'INVERT')]}),
("graph.select_box", {"type": 'Q', "value": 'PRESS'},
{"properties": [("axis_range", False), ("include_handles", False)]}),
{"properties": [("axis_range", False)]}),
("graph.select_box", {"type": 'Q', "value": 'PRESS', "alt": True},
{"properties": [("axis_range", True), ("include_handles", False)]}),
("graph.select_box", {"type": 'Q', "value": 'PRESS', "ctrl": True},
{"properties": [("axis_range", False), ("include_handles", True)]}),
("graph.select_box", {"type": 'Q', "value": 'PRESS', "ctrl": True, "alt": True},
{"properties": [("axis_range", True), ("include_handles", True)]}),
{"properties": [("axis_range", True)]}),
("graph.select_box", {"type": 'EVT_TWEAK_L', "value": 'ANY'},
{"properties":[("tweak", True), ("axis_range", False), ("include_handles", False), ("mode", 'SET')]}),
{"properties":[("tweak", True), ("axis_range", False), ("mode", 'SET')]}),
("graph.select_box", {"type": 'EVT_TWEAK_L', "value": 'ANY', "shift": True},
{"properties":[("tweak", True), ("axis_range", False), ("include_handles", False), ("mode", 'ADD')]}),
{"properties":[("tweak", True), ("axis_range", False), ("mode", 'ADD')]}),
("graph.select_box", {"type": 'EVT_TWEAK_L', "value": 'ANY', "ctrl": True},
{"properties":[("tweak", True), ("axis_range", False),("include_handles", False), ("mode", 'SUB')]}),
{"properties":[("tweak", True), ("axis_range", False), ("mode", 'SUB')]}),
("graph.select_more", {"type": 'UP_ARROW', "value": 'PRESS'}, None),
("graph.select_less", {"type": 'DOWN_ARROW', "value": 'PRESS'}, None),
("graph.select_linked", {"type": 'RIGHT_BRACKET', "value": 'PRESS'}, None),
@@ -1587,7 +1583,7 @@ def km_text(params):
{"properties": [("direction", 'UP')]}),
("text.move_lines", {"type": 'DOWN_ARROW', "value": 'PRESS', "shift": True, "ctrl": True},
{"properties": [("direction", 'DOWN')]}),
("text.indent", {"type": 'TAB', "value": 'PRESS'}, None),
("text.indent_or_autocomplete", {"type": 'TAB', "value": 'PRESS'}, None),
("text.unindent", {"type": 'TAB', "value": 'PRESS', "shift": True}, None),
("text.uncomment", {"type": 'D', "value": 'PRESS', "shift": True, "ctrl": True}, None),
("text.move", {"type": 'HOME', "value": 'PRESS'},
@@ -1668,7 +1664,6 @@ def km_text(params):
("text.line_break", {"type": 'RET', "value": 'PRESS'}, None),
("text.line_break", {"type": 'NUMPAD_ENTER', "value": 'PRESS'}, None),
op_menu("TEXT_MT_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS', "any": True}),
("text.autocomplete", {"type": 'SPACE', "value": 'PRESS', "ctrl": True}, None),
("text.line_number", {"type": 'TEXTINPUT', "value": 'ANY', "any": True}, None),
("text.insert", {"type": 'TEXTINPUT', "value": 'ANY', "any": True}, None),
])
@@ -1878,7 +1873,6 @@ def km_console(params):
{"properties": [("interactive", True)]}),
("console.execute", {"type": 'NUMPAD_ENTER', "value": 'PRESS'},
{"properties": [("interactive", True)]}),
("console.autocomplete", {"type": 'SPACE', "value": 'PRESS', "ctrl": True}, None),
("console.copy_as_script", {"type": 'C', "value": 'PRESS', "shift": True, "ctrl": True}, None),
("console.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
("console.paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
@@ -1886,10 +1880,10 @@ def km_console(params):
("console.select_word", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'}, None),
("console.insert", {"type": 'TAB', "value": 'PRESS', "ctrl": True},
{"properties": [("text", '\t')]}),
("console.indent", {"type": 'TAB', "value": 'PRESS'}, None),
("console.indent_or_autocomplete", {"type": 'TAB', "value": 'PRESS'}, None),
("console.unindent", {"type": 'TAB', "value": 'PRESS', "shift": True}, None),
("console.insert", {"type": 'TEXTINPUT', "value": 'ANY', "any": True}, None),
op_menu("CONSOLE_MT_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}),
("console.insert", {"type": 'TEXTINPUT', "value": 'ANY', "any": True}, None),
])
return keymap

View File

@@ -504,7 +504,7 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
/* do not return this loop if clipped, we want every character tested */
blf_glyph_render(font, gc, g, (float)pen_x, (float)pen_y);
col = BLI_wcwidth((wchar_t)c);
col = BLI_wcwidth((char32_t)c);
if (col < 0) {
col = 1;
}

View File

@@ -35,6 +35,8 @@ struct Path;
struct TextBox;
struct rctf;
typedef int eBezTriple_Flag__Alias;
typedef struct CurveCache {
ListBase disp;
ListBase bev;
@@ -242,6 +244,12 @@ void BKE_nurb_handle_calc(struct BezTriple *bezt,
struct BezTriple *next,
const bool is_fcurve,
const char smoothing);
void BKE_nurb_handle_calc_ex(struct BezTriple *bezt,
struct BezTriple *prev,
struct BezTriple *next,
const eBezTriple_Flag__Alias handle_sel_flag,
const bool is_fcurve,
const char smoothing);
void BKE_nurb_handle_calc_simple(struct Nurb *nu, struct BezTriple *bezt);
void BKE_nurb_handle_calc_simple_auto(struct Nurb *nu, struct BezTriple *bezt);
@@ -249,7 +257,9 @@ void BKE_nurb_handle_smooth_fcurve(struct BezTriple *bezt, int total, bool cycli
void BKE_nurb_handles_calc(struct Nurb *nu);
void BKE_nurb_handles_autocalc(struct Nurb *nu, int flag);
void BKE_nurb_bezt_handle_test(struct BezTriple *bezt, const bool use_handle);
void BKE_nurb_bezt_handle_test(struct BezTriple *bezt,
const eBezTriple_Flag__Alias sel_flag,
const bool use_handle);
void BKE_nurb_handles_test(struct Nurb *nu, const bool use_handles);
/* **** Depsgraph evaluation **** */

View File

@@ -328,7 +328,8 @@ eFCU_Cycle_Type BKE_fcurve_get_cycle_type(struct FCurve *fcu);
/* -------- Curve Sanity -------- */
void calchandles_fcurve(struct FCurve *fcu);
void testhandles_fcurve(struct FCurve *fcu, const bool use_handle);
void calchandles_fcurve_ex(struct FCurve *fcu, eBezTriple_Flag handle_sel_flag);
void testhandles_fcurve(struct FCurve *fcu, eBezTriple_Flag sel_flag, const bool use_handle);
void sort_time_fcurve(struct FCurve *fcu);
short test_time_fcurve(struct FCurve *fcu);

View File

@@ -27,8 +27,6 @@
extern "C" {
#endif
#include <wchar.h>
struct CharInfo;
struct Curve;
struct Main;
@@ -48,7 +46,7 @@ typedef struct EditFontSelBox {
} EditFontSelBox;
typedef struct EditFont {
wchar_t *textbuf;
char32_t *textbuf;
struct CharInfo *textbufinfo;
/* array of rectangles & rotation */
@@ -90,7 +88,7 @@ bool BKE_vfont_to_curve_ex(struct Object *ob,
struct Curve *cu,
int mode,
struct ListBase *r_nubase,
const wchar_t **r_text,
const char32_t **r_text,
int *r_text_len,
bool *r_text_free,
struct CharTrans **r_chartransdata);
@@ -101,13 +99,13 @@ int BKE_vfont_select_get(struct Object *ob, int *r_start, int *r_end);
void BKE_vfont_select_clamp(struct Object *ob);
void BKE_vfont_clipboard_free(void);
void BKE_vfont_clipboard_set(const wchar_t *text_buf,
void BKE_vfont_clipboard_set(const char32_t *text_buf,
const struct CharInfo *info_buf,
const size_t len);
void BKE_vfont_clipboard_get(wchar_t **r_text_buf,
void BKE_vfont_clipboard_get(char32_t **r_text_buf,
struct CharInfo **r_info_buf,
size_t *r_len_utf8,
size_t *r_len_wchar);
size_t *r_len_utf32);
#ifdef __cplusplus
}

View File

@@ -3201,6 +3201,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
static void calchandleNurb_intern(BezTriple *bezt,
const BezTriple *prev,
const BezTriple *next,
eBezTriple_Flag handle_sel_flag,
bool is_fcurve,
bool skip_align,
char fcurve_smoothing)
@@ -3402,7 +3403,7 @@ static void calchandleNurb_intern(BezTriple *bezt,
len_ratio = len_a / len_b;
if (bezt->f1 & SELECT) { /* order of calculation */
if (bezt->f1 & handle_sel_flag) { /* order of calculation */
if (ELEM(bezt->h2, HD_ALIGN, HD_ALIGN_DOUBLESIDE)) { /* aligned */
if (len_a > eps) {
len = 1.0f / len_ratio;
@@ -3443,7 +3444,7 @@ static void calchandleNurb_intern(BezTriple *bezt,
#undef p2_h2
}
static void calchandlesNurb_intern(Nurb *nu, bool skip_align)
static void calchandlesNurb_intern(Nurb *nu, eBezTriple_Flag handle_sel_flag, bool skip_align)
{
BezTriple *bezt, *prev, *next;
int a;
@@ -3466,7 +3467,7 @@ static void calchandlesNurb_intern(Nurb *nu, bool skip_align)
next = bezt + 1;
while (a--) {
calchandleNurb_intern(bezt, prev, next, 0, skip_align, 0);
calchandleNurb_intern(bezt, prev, next, handle_sel_flag, 0, skip_align, 0);
prev = bezt;
if (a == 1) {
if (nu->flagu & CU_NURB_CYCLIC) {
@@ -4038,15 +4039,36 @@ void BKE_nurb_handle_smooth_fcurve(BezTriple *bezt, int total, bool cycle)
}
}
/**
* Recalculate the handles of a nurb bezier-triple. Acts based on handle selection with `SELECT`
* flag. To use a different flag, use #BKE_nurb_handle_calc_ex().
*/
void BKE_nurb_handle_calc(
BezTriple *bezt, BezTriple *prev, BezTriple *next, const bool is_fcurve, const char smoothing)
{
calchandleNurb_intern(bezt, prev, next, is_fcurve, false, smoothing);
calchandleNurb_intern(bezt, prev, next, SELECT, is_fcurve, false, smoothing);
}
/**
* Variant of #BKE_nurb_handle_calc() that allows calculating based on a different select flag.
*
* \param sel_flag: The flag (bezt.f1/2/3) value to use to determine selection. Usually `SELECT`,
* but may want to use a different one at times (if caller does not operate on
* selection).
*/
void BKE_nurb_handle_calc_ex(BezTriple *bezt,
BezTriple *prev,
BezTriple *next,
const eBezTriple_Flag__Alias handle_sel_flag,
const bool is_fcurve,
const char smoothing)
{
calchandleNurb_intern(bezt, prev, next, handle_sel_flag, is_fcurve, false, smoothing);
}
void BKE_nurb_handles_calc(Nurb *nu) /* first, if needed, set handle flags */
{
calchandlesNurb_intern(nu, false);
calchandlesNurb_intern(nu, SELECT, false);
}
/**
@@ -4101,11 +4123,21 @@ void BKE_nurb_handle_calc_simple_auto(Nurb *nu, BezTriple *bezt)
}
/**
* Update selected handle types to ensure valid state, e.g. deduce "Auto" types to concrete ones.
* Thereby \a sel_flag defines what qualifies as selected.
* Use when something has changed handle positions.
*
* The caller needs to recalculate handles.
*
* \param sel_flag: The flag (bezt.f1/2/3) value to use to determine selection. Usually `SELECT`,
* but may want to use a different one at times (if caller does not operate on
* selection).
* \param use_handle: Check selection state of individual handles, otherwise always update both
* handles if the key is selected.
*/
void BKE_nurb_bezt_handle_test(BezTriple *bezt, const bool use_handle)
void BKE_nurb_bezt_handle_test(BezTriple *bezt,
const eBezTriple_Flag__Alias sel_flag,
const bool use_handle)
{
short flag = 0;
@@ -4114,18 +4146,18 @@ void BKE_nurb_bezt_handle_test(BezTriple *bezt, const bool use_handle)
#define SEL_F3 (1 << 2)
if (use_handle) {
if (bezt->f1 & SELECT) {
if (bezt->f1 & sel_flag) {
flag |= SEL_F1;
}
if (bezt->f2 & SELECT) {
if (bezt->f2 & sel_flag) {
flag |= SEL_F2;
}
if (bezt->f3 & SELECT) {
if (bezt->f3 & sel_flag) {
flag |= SEL_F3;
}
}
else {
flag = (bezt->f2 & SELECT) ? (SEL_F1 | SEL_F2 | SEL_F3) : 0;
flag = (bezt->f2 & sel_flag) ? (SEL_F1 | SEL_F2 | SEL_F3) : 0;
}
/* check for partial selection */
@@ -4166,7 +4198,7 @@ void BKE_nurb_handles_test(Nurb *nu, const bool use_handle)
bezt = nu->bezt;
a = nu->pntsu;
while (a--) {
BKE_nurb_bezt_handle_test(bezt, use_handle);
BKE_nurb_bezt_handle_test(bezt, SELECT, use_handle);
bezt++;
}
@@ -4639,7 +4671,7 @@ void BKE_curve_nurbs_vert_coords_apply_with_mat4(ListBase *lb,
}
}
calchandlesNurb_intern(nu, true);
calchandlesNurb_intern(nu, SELECT, true);
}
}
@@ -4677,7 +4709,7 @@ void BKE_curve_nurbs_vert_coords_apply(ListBase *lb,
}
}
calchandlesNurb_intern(nu, true);
calchandlesNurb_intern(nu, SELECT, true);
}
}

View File

@@ -1036,10 +1036,14 @@ static BezTriple *cycle_offset_triple(
return out;
}
/* This function recalculates the handles of an F-Curve
* If the BezTriples have been rearranged, sort them first before using this.
/**
* Variant of #calchandles_fcurve() that allows calculating based on a different select flag.
*
* \param sel_flag: The flag (bezt.f1/2/3) value to use to determine selection. Usually `SELECT`,
* but may want to use a different one at times (if caller does not operate on
* selection).
*/
void calchandles_fcurve(FCurve *fcu)
void calchandles_fcurve_ex(FCurve *fcu, eBezTriple_Flag handle_sel_flag)
{
BezTriple *bezt, *prev, *next;
int a = fcu->totvert;
@@ -1075,7 +1079,7 @@ void calchandles_fcurve(FCurve *fcu)
}
/* calculate auto-handles */
BKE_nurb_handle_calc(bezt, prev, next, true, fcu->auto_smoothing);
BKE_nurb_handle_calc_ex(bezt, prev, next, handle_sel_flag, true, fcu->auto_smoothing);
/* for automatic ease in and out */
if (BEZT_IS_AUTOH(bezt) && !cycle) {
@@ -1121,7 +1125,29 @@ void calchandles_fcurve(FCurve *fcu)
}
}
void testhandles_fcurve(FCurve *fcu, const bool use_handle)
/**
* This function recalculates the handles of an F-Curve. Acts based on selection with `SELECT`
* flag. To use a different flag, use #calchandles_fcurve_ex().
*
* If the BezTriples have been rearranged, sort them first before using this.
*/
void calchandles_fcurve(FCurve *fcu)
{
calchandles_fcurve_ex(fcu, SELECT);
}
/**
* Update handles, making sure the handle-types are valid (e.g. correctly deduced from an "Auto"
* type), and recalculating their position vectors.
* Use when something has changed handle positions.
*
* \param sel_flag: The flag (bezt.f1/2/3) value to use to determine selection. Usually `SELECT`,
* but may want to use a different one at times (if caller does not operate on
* selection).
* \param use_handle: Check selection state of individual handles, otherwise always update both
* handles if the key is selected.
*/
void testhandles_fcurve(FCurve *fcu, eBezTriple_Flag sel_flag, const bool use_handle)
{
BezTriple *bezt;
unsigned int a;
@@ -1133,11 +1159,11 @@ void testhandles_fcurve(FCurve *fcu, const bool use_handle)
/* loop over beztriples */
for (a = 0, bezt = fcu->bezt; a < fcu->totvert; a++, bezt++) {
BKE_nurb_bezt_handle_test(bezt, use_handle);
BKE_nurb_bezt_handle_test(bezt, sel_flag, use_handle);
}
/* recalculate handles */
calchandles_fcurve(fcu);
calchandles_fcurve_ex(fcu, sel_flag);
}
/* This function sorts BezTriples so that they are arranged in chronological order,

View File

@@ -25,7 +25,6 @@
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <wchar.h>
#include <wctype.h>
#include "CLG_log.h"
@@ -691,7 +690,7 @@ static bool vfont_to_curve(Object *ob,
int mode,
VFontToCurveIter *iter_data,
ListBase *r_nubase,
const wchar_t **r_text,
const char32_t **r_text,
int *r_text_len,
bool *r_text_free,
struct CharTrans **r_chartransdata)
@@ -712,8 +711,8 @@ static bool vfont_to_curve(Object *ob,
int curbox;
int selstart, selend;
int cnr = 0, lnr = 0, wsnr = 0;
const wchar_t *mem = NULL;
wchar_t ascii;
const char32_t *mem = NULL;
char32_t ascii;
bool ok = false;
const float font_size = cu->fsize * iter_data->scale_to_fit;
const float xof_scale = cu->xof / font_size;
@@ -759,16 +758,16 @@ static bool vfont_to_curve(Object *ob,
custrinfo = ef->textbufinfo;
}
else {
wchar_t *mem_tmp;
char32_t *mem_tmp;
slen = cu->len_wchar;
/* Create unicode string */
mem_tmp = MEM_malloc_arrayN((slen + 1), sizeof(wchar_t), "convertedmem");
mem_tmp = MEM_malloc_arrayN((slen + 1), sizeof(*mem_tmp), "convertedmem");
if (!mem_tmp) {
return ok;
}
BLI_strncpy_wchar_from_utf8(mem_tmp, cu->str, slen + 1);
BLI_str_utf8_as_utf32(mem_tmp, cu->str, slen + 1);
if (cu->strinfo == NULL) { /* old file */
cu->strinfo = MEM_calloc_arrayN((slen + 4), sizeof(CharInfo), "strinfo compat");
@@ -1605,7 +1604,7 @@ bool BKE_vfont_to_curve_ex(Object *ob,
Curve *cu,
int mode,
ListBase *r_nubase,
const wchar_t **r_text,
const char32_t **r_text,
int *r_text_len,
bool *r_text_free,
struct CharTrans **r_chartransdata)
@@ -1649,9 +1648,9 @@ bool BKE_vfont_to_curve(Object *ob, int mode)
* \{ */
static struct {
wchar_t *text_buffer;
char32_t *text_buffer;
CharInfo *info_buffer;
size_t len_wchar;
size_t len_utf32;
size_t len_utf8;
} g_vfont_clipboard = {NULL};
@@ -1659,19 +1658,19 @@ void BKE_vfont_clipboard_free(void)
{
MEM_SAFE_FREE(g_vfont_clipboard.text_buffer);
MEM_SAFE_FREE(g_vfont_clipboard.info_buffer);
g_vfont_clipboard.len_wchar = 0;
g_vfont_clipboard.len_utf32 = 0;
g_vfont_clipboard.len_utf8 = 0;
}
void BKE_vfont_clipboard_set(const wchar_t *text_buf, const CharInfo *info_buf, const size_t len)
void BKE_vfont_clipboard_set(const char32_t *text_buf, const CharInfo *info_buf, const size_t len)
{
wchar_t *text;
char32_t *text;
CharInfo *info;
/* clean previous buffers*/
BKE_vfont_clipboard_free();
text = MEM_malloc_arrayN((len + 1), sizeof(wchar_t), __func__);
text = MEM_malloc_arrayN((len + 1), sizeof(*text), __func__);
if (text == NULL) {
return;
}
@@ -1682,21 +1681,21 @@ void BKE_vfont_clipboard_set(const wchar_t *text_buf, const CharInfo *info_buf,
return;
}
memcpy(text, text_buf, len * sizeof(wchar_t));
memcpy(text, text_buf, len * sizeof(*text));
text[len] = '\0';
memcpy(info, info_buf, len * sizeof(CharInfo));
/* store new buffers */
g_vfont_clipboard.text_buffer = text;
g_vfont_clipboard.info_buffer = info;
g_vfont_clipboard.len_utf8 = BLI_wstrlen_utf8(text);
g_vfont_clipboard.len_wchar = len;
g_vfont_clipboard.len_utf8 = BLI_str_utf32_as_utf8_len(text);
g_vfont_clipboard.len_utf32 = len;
}
void BKE_vfont_clipboard_get(wchar_t **r_text_buf,
void BKE_vfont_clipboard_get(char32_t **r_text_buf,
CharInfo **r_info_buf,
size_t *r_len_utf8,
size_t *r_len_wchar)
size_t *r_len_utf32)
{
if (r_text_buf) {
*r_text_buf = g_vfont_clipboard.text_buffer;
@@ -1706,8 +1705,8 @@ void BKE_vfont_clipboard_get(wchar_t **r_text_buf,
*r_info_buf = g_vfont_clipboard.info_buffer;
}
if (r_len_wchar) {
*r_len_wchar = g_vfont_clipboard.len_wchar;
if (r_len_utf32) {
*r_len_utf32 = g_vfont_clipboard.len_utf32;
}
if (r_len_utf8) {

View File

@@ -36,6 +36,7 @@
#include "BKE_main.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
@@ -148,6 +149,10 @@ void BKE_override_library_clear(IDOverrideLibrary *override, const bool do_id_us
{
BLI_assert(override != NULL);
if (override->runtime != NULL) {
BLI_ghash_clear(override->runtime, NULL, NULL);
}
for (IDOverrideLibraryProperty *op = override->properties.first; op; op = op->next) {
bke_override_property_clear(op);
}
@@ -164,6 +169,11 @@ void BKE_override_library_free(struct IDOverrideLibrary **override, const bool d
{
BLI_assert(*override != NULL);
if ((*override)->runtime != NULL) {
BLI_ghash_free((*override)->runtime, NULL, NULL);
(*override)->runtime = NULL;
}
BKE_override_library_clear(*override, do_id_user);
MEM_freeN(*override);
*override = NULL;
@@ -285,15 +295,28 @@ bool BKE_override_library_create_from_tag(Main *bmain)
return ret;
}
/* We only build override GHash on request. */
BLI_INLINE IDOverrideLibraryRuntime *override_library_rna_path_mapping_ensure(
IDOverrideLibrary *override)
{
if (override->runtime == NULL) {
override->runtime = BLI_ghash_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, __func__);
for (IDOverrideLibraryProperty *op = override->properties.first; op != NULL; op = op->next) {
BLI_ghash_insert(override->runtime, op->rna_path, op);
}
}
return override->runtime;
}
/**
* Find override property from given RNA path, if it exists.
*/
IDOverrideLibraryProperty *BKE_override_library_property_find(IDOverrideLibrary *override,
const char *rna_path)
{
/* XXX TODO we'll most likely want a runtime ghash to store that mapping at some point. */
return BLI_findstring_ptr(
&override->properties, rna_path, offsetof(IDOverrideLibraryProperty, rna_path));
IDOverrideLibraryRuntime *override_runtime = override_library_rna_path_mapping_ensure(override);
return BLI_ghash_lookup(override_runtime, rna_path);
}
/**
@@ -303,7 +326,6 @@ IDOverrideLibraryProperty *BKE_override_library_property_get(IDOverrideLibrary *
const char *rna_path,
bool *r_created)
{
/* XXX TODO we'll most likely want a runtime ghash to store that mapping at some point. */
IDOverrideLibraryProperty *op = BKE_override_library_property_find(override, rna_path);
if (op == NULL) {
@@ -311,6 +333,10 @@ IDOverrideLibraryProperty *BKE_override_library_property_get(IDOverrideLibrary *
op->rna_path = BLI_strdup(rna_path);
BLI_addtail(&override->properties, op);
IDOverrideLibraryRuntime *override_runtime = override_library_rna_path_mapping_ensure(
override);
BLI_ghash_insert(override_runtime, op->rna_path, op);
if (r_created) {
*r_created = true;
}
@@ -355,6 +381,9 @@ void BKE_override_library_property_delete(IDOverrideLibrary *override,
IDOverrideLibraryProperty *override_property)
{
bke_override_property_clear(override_property);
if (override->runtime != NULL) {
BLI_ghash_remove(override->runtime, override_property->rna_path, NULL, NULL);
}
BLI_freelinkN(&override->properties, override_property);
}

View File

@@ -491,7 +491,7 @@ static void make_duplis_font(const DupliContext *ctx)
float vec[3], obmat[4][4], pmat[4][4], fsize, xof, yof;
int text_len, a;
size_t family_len;
const wchar_t *text = NULL;
const char32_t *text = NULL;
bool text_free = false;
/* font dupliverts not supported inside collections */

View File

@@ -25,7 +25,6 @@
#include <string.h> /* strstr */
#include <sys/types.h>
#include <sys/stat.h>
#include <wchar.h>
#include <wctype.h>
#include "MEM_guardedalloc.h"

View File

@@ -45,7 +45,7 @@ void BLI_str_cursor_step_utf8(const char *str,
eStrCursorJumpType jump,
bool use_init_step);
void BLI_str_cursor_step_wchar(const wchar_t *str,
void BLI_str_cursor_step_utf32(const char32_t *str,
size_t maxlen,
int *pos,
eStrCursorJumpDirection direction,

View File

@@ -26,6 +26,7 @@ extern "C" {
#endif
#include "BLI_compiler_attrs.h"
#include "BLI_sys_types.h"
char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy)
ATTR_NONNULL();
@@ -48,6 +49,13 @@ unsigned int BLI_str_utf8_as_unicode_and_size_safe(const char *__restrict p,
unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index)
ATTR_NONNULL();
size_t BLI_str_utf8_from_unicode(unsigned int c, char *outbuf);
size_t BLI_str_utf8_as_utf32(char32_t *__restrict dst_w,
const char *__restrict src_c,
const size_t maxncpy) ATTR_NONNULL();
size_t BLI_str_utf32_as_utf8(char *__restrict dst,
const char32_t *__restrict src,
const size_t maxncpy) ATTR_NONNULL();
size_t BLI_str_utf32_as_utf8_len(const char32_t *src) ATTR_NONNULL();
char *BLI_str_find_prev_char_utf8(const char *str, const char *p) ATTR_NONNULL();
char *BLI_str_find_next_char_utf8(const char *p, const char *end) ATTR_NONNULL(1);
@@ -68,8 +76,8 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst,
const size_t maxcpy) ATTR_NONNULL();
/* count columns that character/string occupies, based on wcwidth.c */
int BLI_wcwidth(wchar_t ucs);
int BLI_wcswidth(const wchar_t *pwcs, size_t n) ATTR_NONNULL();
int BLI_wcwidth(char32_t ucs);
int BLI_wcswidth(const char32_t *pwcs, size_t n) ATTR_NONNULL();
/* warning, can return -1 on bad chars */
int BLI_str_utf8_char_width(const char *p) ATTR_NONNULL();
int BLI_str_utf8_char_width_safe(const char *p) ATTR_NONNULL();

View File

@@ -72,6 +72,15 @@ typedef uint64_t u_int64_t;
#include <stddef.h> /* size_t define */
#include <stdbool.h>
#ifndef __cplusplus
# if defined(__APPLE__)
/* The <uchar.h> standard header is missing on macOS. */
typedef unsigned int char32_t;
# else
# include <uchar.h>
# endif
#endif
typedef unsigned int uint;
typedef unsigned short ushort;
typedef unsigned long ulong;

View File

@@ -211,12 +211,12 @@ void BLI_str_cursor_step_utf8(const char *str,
}
}
/* wchar_t version of BLI_str_cursor_step_utf8 (keep in sync!)
/* UTF32 version of BLI_str_cursor_step_utf8 (keep in sync!)
* less complex since it doesn't need to do multi-byte stepping.
*/
/* helper funcs so we can match BLI_str_cursor_step_utf8 */
static bool wchar_t_step_next(const wchar_t *UNUSED(str), size_t maxlen, int *pos)
static bool cursor_step_next_utf32(const char32_t *UNUSED(str), size_t maxlen, int *pos)
{
if ((*pos) >= (int)maxlen) {
return false;
@@ -225,7 +225,7 @@ static bool wchar_t_step_next(const wchar_t *UNUSED(str), size_t maxlen, int *po
return true;
}
static bool wchar_t_step_prev(const wchar_t *UNUSED(str), size_t UNUSED(maxlen), int *pos)
static bool cursor_step_prev_utf32(const char32_t *UNUSED(str), size_t UNUSED(maxlen), int *pos)
{
if ((*pos) <= 0) {
return false;
@@ -234,7 +234,7 @@ static bool wchar_t_step_prev(const wchar_t *UNUSED(str), size_t UNUSED(maxlen),
return true;
}
void BLI_str_cursor_step_wchar(const wchar_t *str,
void BLI_str_cursor_step_utf32(const char32_t *str,
size_t maxlen,
int *pos,
eStrCursorJumpDirection direction,
@@ -245,7 +245,7 @@ void BLI_str_cursor_step_wchar(const wchar_t *str,
if (direction == STRCUR_DIR_NEXT) {
if (use_init_step) {
wchar_t_step_next(str, maxlen, pos);
cursor_step_next_utf32(str, maxlen, pos);
}
else {
BLI_assert(jump == STRCUR_JUMP_DELIM);
@@ -259,7 +259,7 @@ void BLI_str_cursor_step_wchar(const wchar_t *str,
* look at function cursor_delim_type_unicode() for complete
* list of special character, ctr -> */
while ((*pos) < maxlen) {
if (wchar_t_step_next(str, maxlen, pos)) {
if (cursor_step_next_utf32(str, maxlen, pos)) {
if ((jump != STRCUR_JUMP_ALL) &&
(delim_type != cursor_delim_type_unicode((uint)str[*pos]))) {
break;
@@ -273,7 +273,7 @@ void BLI_str_cursor_step_wchar(const wchar_t *str,
}
else if (direction == STRCUR_DIR_PREV) {
if (use_init_step) {
wchar_t_step_prev(str, maxlen, pos);
cursor_step_prev_utf32(str, maxlen, pos);
}
else {
BLI_assert(jump == STRCUR_JUMP_DELIM);
@@ -288,7 +288,7 @@ void BLI_str_cursor_step_wchar(const wchar_t *str,
* list of special character, ctr -> */
while ((*pos) > 0) {
const int pos_prev = *pos;
if (wchar_t_step_prev(str, maxlen, pos)) {
if (cursor_step_prev_utf32(str, maxlen, pos)) {
if ((jump != STRCUR_JUMP_ALL) &&
(delim_type != cursor_delim_type_unicode((uint)str[*pos]))) {
/* left only: compensate for index/change in direction */

View File

@@ -430,6 +430,11 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w,
size_t step = 0;
uint unicode = BLI_str_utf8_as_unicode_and_size(src_c, &step);
if (unicode != BLI_UTF8_ERR) {
/* TODO: `wchar_t` type is an implementation-defined and may represent
* 16-bit or 32-bit depending on operating system.
* So the ideal would be to do the corresponding encoding.
* But for now just assert that it has no conflicting use. */
BLI_assert(step <= sizeof(wchar_t));
*dst_w = (wchar_t)unicode;
src_c += step;
}
@@ -451,12 +456,12 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w,
/* count columns that character/string occupies, based on wcwidth.c */
int BLI_wcwidth(wchar_t ucs)
int BLI_wcwidth(char32_t ucs)
{
return mk_wcwidth(ucs);
}
int BLI_wcswidth(const wchar_t *pwcs, size_t n)
int BLI_wcswidth(const char32_t *pwcs, size_t n)
{
return mk_wcswidth(pwcs, n);
}
@@ -468,7 +473,7 @@ int BLI_str_utf8_char_width(const char *p)
return -1;
}
return BLI_wcwidth((wchar_t)unicode);
return BLI_wcwidth((char32_t)unicode);
}
int BLI_str_utf8_char_width_safe(const char *p)
@@ -480,7 +485,7 @@ int BLI_str_utf8_char_width_safe(const char *p)
return 1;
}
columns = BLI_wcwidth((wchar_t)unicode);
columns = BLI_wcwidth((char32_t)unicode);
return (columns < 0) ? 1 : columns;
}
@@ -726,6 +731,88 @@ size_t BLI_str_utf8_from_unicode(uint c, char *outbuf)
return len;
}
size_t BLI_str_utf8_as_utf32(char32_t *__restrict dst_w,
const char *__restrict src_c,
const size_t maxncpy)
{
const size_t maxlen = maxncpy - 1;
size_t len = 0;
BLI_assert(maxncpy != 0);
#ifdef DEBUG_STRSIZE
memset(dst_w, 0xff, sizeof(*dst_w) * maxncpy);
#endif
while (*src_c && len != maxlen) {
size_t step = 0;
uint unicode = BLI_str_utf8_as_unicode_and_size(src_c, &step);
if (unicode != BLI_UTF8_ERR) {
*dst_w = unicode;
src_c += step;
}
else {
*dst_w = '?';
src_c = BLI_str_find_next_char_utf8(src_c, NULL);
}
dst_w++;
len++;
}
*dst_w = 0;
return len;
}
size_t BLI_str_utf32_as_utf8(char *__restrict dst,
const char32_t *__restrict src,
const size_t maxncpy)
{
const size_t maxlen = maxncpy - 1;
/* 6 is max utf8 length of an unicode char. */
const int64_t maxlen_secured = (int64_t)maxlen - 6;
size_t len = 0;
BLI_assert(maxncpy != 0);
#ifdef DEBUG_STRSIZE
memset(dst, 0xff, sizeof(*dst) * maxncpy);
#endif
while (*src && len <= maxlen_secured) {
len += BLI_str_utf8_from_unicode((uint)*src++, dst + len);
}
/* We have to be more careful for the last six bytes,
* to avoid buffer overflow in case utf8-encoded char would be too long for our dst buffer. */
while (*src) {
char t[6];
size_t l = BLI_str_utf8_from_unicode((uint)*src++, t);
BLI_assert(l <= 6);
if (len + l > maxlen) {
break;
}
memcpy(dst + len, t, l);
len += l;
}
dst[len] = '\0';
return len;
}
/* utf32 len in utf8 */
size_t BLI_str_utf32_as_utf8_len(const char32_t *src)
{
size_t len = 0;
while (*src) {
len += BLI_str_utf8_from_unicode((uint)*src++, NULL);
}
return len;
}
/* was g_utf8_find_prev_char */
/**
* BLI_str_find_prev_char_utf8:

View File

@@ -2668,6 +2668,7 @@ static void direct_link_id(FileData *fd, ID *id)
if (id->override_library) {
id->override_library = newdataadr(fd, id->override_library);
link_list_ex(fd, &id->override_library->properties, direct_link_id_override_property_cb);
id->override_library->runtime = NULL;
}
DrawDataList *drawdata = DRW_drawdatalist_from_id(id);

View File

@@ -5492,7 +5492,11 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv)
}
else { /* Get the last of the two BoundVerts. */
weld2 = bndv;
move_weld_profile_planes(bv, weld1, weld2); /* Profile recalculated in next loop. */
move_weld_profile_planes(bv, weld1, weld2);
if (!bp->use_custom_profile) { /* Else profile recalculated in next loop. */
calculate_profile(bp, weld1, !weld1->is_profile_start, false);
calculate_profile(bp, weld2, !weld2->is_profile_start, false);
}
}
}
} while ((bndv = bndv->next) != vm->boundstart);

View File

@@ -1403,9 +1403,11 @@ void DepsgraphRelationBuilder::build_action(bAction *action)
if (built_map_.checkIsBuiltAndTag(action)) {
return;
}
TimeSourceKey time_src_key;
ComponentKey animation_key(&action->id, NodeType::ANIMATION);
add_relation(time_src_key, animation_key, "TimeSrc -> Animation");
if (!BLI_listbase_is_empty(&action->curves)) {
TimeSourceKey time_src_key;
ComponentKey animation_key(&action->id, NodeType::ANIMATION);
add_relation(time_src_key, animation_key, "TimeSrc -> Animation");
}
}
void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)

View File

@@ -501,10 +501,16 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac)
ok |= KEYFRAME_OK_KEY; \
\
if (ked && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) { \
if (check(0)) \
ok |= KEYFRAME_OK_H1; \
if (check(2)) \
ok |= KEYFRAME_OK_H2; \
/* Only act on visible items, so check handle visiblity state. */ \
const bool handles_visible = ((ked->iterflags & KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE) ? \
(BEZT_ISSEL_ANY(bezt)) : \
true); \
if (handles_visible) { \
if (check(0)) \
ok |= KEYFRAME_OK_H1; \
if (check(2)) \
ok |= KEYFRAME_OK_H2; \
} \
} \
} \
(void)0
@@ -1054,7 +1060,11 @@ KeyframeEditFunc ANIM_editkeyframes_mirror(short type)
/* Sets the selected bezier handles to type 'auto' */
static short set_bezier_auto(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
if ((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) {
/* If the key is selected, always apply to both handles. */
if (bezt->f2 & SELECT) {
bezt->h1 = bezt->h2 = HD_AUTO;
}
else {
if (bezt->f1 & SELECT) {
bezt->h1 = HD_AUTO;
}
@@ -1064,6 +1074,7 @@ static short set_bezier_auto(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
ENSURE_HANDLES_MATCH(bezt);
}
return 0;
}
@@ -1072,7 +1083,11 @@ static short set_bezier_auto(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
*/
static short set_bezier_auto_clamped(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
if ((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) {
/* If the key is selected, always apply to both handles. */
if (bezt->f2 & SELECT) {
bezt->h1 = bezt->h2 = HD_AUTO_ANIM;
}
else {
if (bezt->f1 & SELECT) {
bezt->h1 = HD_AUTO_ANIM;
}
@@ -1082,18 +1097,26 @@ static short set_bezier_auto_clamped(KeyframeEditData *UNUSED(ked), BezTriple *b
ENSURE_HANDLES_MATCH(bezt);
}
return 0;
}
/* Sets the selected bezier handles to type 'vector' */
static short set_bezier_vector(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
if (bezt->f1 & SELECT) {
bezt->h1 = HD_VECT;
/* If the key is selected, always apply to both handles. */
if (bezt->f2 & SELECT) {
bezt->h1 = bezt->h2 = HD_VECT;
}
if (bezt->f3 & SELECT) {
bezt->h2 = HD_VECT;
else {
if (bezt->f1 & SELECT) {
bezt->h1 = HD_VECT;
}
if (bezt->f3 & SELECT) {
bezt->h2 = HD_VECT;
}
}
return 0;
}
@@ -1114,24 +1137,38 @@ static short bezier_isfree(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
/* Sets selected bezier handles to type 'align' */
static short set_bezier_align(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
if (bezt->f1 & SELECT) {
bezt->h1 = HD_ALIGN;
/* If the key is selected, always apply to both handles. */
if (bezt->f2 & SELECT) {
bezt->h1 = bezt->h2 = HD_ALIGN;
}
if (bezt->f3 & SELECT) {
bezt->h2 = HD_ALIGN;
else {
if (bezt->f1 & SELECT) {
bezt->h1 = HD_ALIGN;
}
if (bezt->f3 & SELECT) {
bezt->h2 = HD_ALIGN;
}
}
return 0;
}
/* Sets selected bezier handles to type 'free' */
static short set_bezier_free(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
if (bezt->f1 & SELECT) {
bezt->h1 = HD_FREE;
/* If the key is selected, always apply to both handles. */
if (bezt->f2 & SELECT) {
bezt->h1 = bezt->h2 = HD_FREE;
}
if (bezt->f3 & SELECT) {
bezt->h2 = HD_FREE;
else {
if (bezt->f1 & SELECT) {
bezt->h1 = HD_FREE;
}
if (bezt->f3 & SELECT) {
bezt->h2 = HD_FREE;
}
}
return 0;
}
@@ -1422,8 +1459,13 @@ KeyframeEditFunc ANIM_editkeyframes_easing(short mode)
static short select_bezier_add(KeyframeEditData *ked, BezTriple *bezt)
{
/* Only act on visible items, so check handle visiblity state. */
const bool handles_visible = ked && ((ked->iterflags & KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE) ?
(BEZT_ISSEL_ANY(bezt)) :
true);
/* if we've got info on what to select, use it, otherwise select all */
if ((ked) && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) {
if ((ked) && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES) && handles_visible) {
if (ked->curflags & KEYFRAME_OK_KEY) {
bezt->f2 |= SELECT;
}
@@ -1443,8 +1485,13 @@ static short select_bezier_add(KeyframeEditData *ked, BezTriple *bezt)
static short select_bezier_subtract(KeyframeEditData *ked, BezTriple *bezt)
{
/* Only act on visible items, so check handle visiblity state. */
const bool handles_visible = ked && ((ked->iterflags & KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE) ?
(BEZT_ISSEL_ANY(bezt)) :
true);
/* if we've got info on what to deselect, use it, otherwise deselect all */
if ((ked) && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES)) {
if ((ked) && (ked->iterflags & KEYFRAME_ITER_INCL_HANDLES) && handles_visible) {
if (ked->curflags & KEYFRAME_OK_KEY) {
bezt->f2 &= ~SELECT;
}

View File

@@ -468,7 +468,8 @@ static int kill_selection(Object *obedit, int ins) /* 1 == new character */
if (ins == 0) {
getfrom++;
}
size = (ef->len * sizeof(wchar_t)) - (selstart * sizeof(wchar_t)) + (offset * sizeof(wchar_t));
size = (ef->len * sizeof(*ef->textbuf)) - (selstart * sizeof(*ef->textbuf)) +
(offset * sizeof(*ef->textbuf));
memmove(ef->textbuf + selstart, ef->textbuf + getfrom, size);
memmove(ef->textbufinfo + selstart,
ef->textbufinfo + getfrom,
@@ -488,7 +489,7 @@ static int kill_selection(Object *obedit, int ins) /* 1 == new character */
/* text_update_edited(C, scene, obedit, 1, FO_EDIT); */
static bool font_paste_wchar(Object *obedit,
const wchar_t *str,
const char32_t *str,
const size_t str_len,
/* optional */
struct CharInfo *str_info)
@@ -507,9 +508,10 @@ static bool font_paste_wchar(Object *obedit,
kill_selection(obedit, 0);
if (str_len) {
int size = (ef->len * sizeof(wchar_t)) - (ef->pos * sizeof(wchar_t)) + sizeof(wchar_t);
int size = (ef->len * sizeof(*ef->textbuf)) - (ef->pos * sizeof(*ef->textbuf)) +
sizeof(*ef->textbuf);
memmove(ef->textbuf + ef->pos + str_len, ef->textbuf + ef->pos, size);
memcpy(ef->textbuf + ef->pos, str, str_len * sizeof(wchar_t));
memcpy(ef->textbuf + ef->pos, str, str_len * sizeof(*ef->textbuf));
memmove(ef->textbufinfo + ef->pos + str_len,
ef->textbufinfo + ef->pos,
@@ -538,9 +540,9 @@ static bool font_paste_utf8(bContext *C, const char *str, const size_t str_len)
int tmplen;
wchar_t *mem = MEM_mallocN((sizeof(wchar_t) * (str_len + 1)), __func__);
char32_t *mem = MEM_mallocN((sizeof(*mem) * (str_len + 1)), __func__);
tmplen = BLI_strncpy_wchar_from_utf8(mem, str, str_len + 1);
tmplen = BLI_str_utf8_as_utf32(mem, str, str_len + 1);
retval = font_paste_wchar(obedit, mem, tmplen, NULL);
@@ -919,7 +921,7 @@ static void copy_selection(Object *obedit)
Curve *cu = obedit->data;
EditFont *ef = cu->editfont;
char *buf = NULL;
wchar_t *text_buf;
char32_t *text_buf;
size_t len_utf8;
/* internal clipboard (for style) */
@@ -930,7 +932,7 @@ static void copy_selection(Object *obedit)
/* system clipboard */
buf = MEM_mallocN(len_utf8 + 1, __func__);
if (buf) {
BLI_strncpy_wchar_as_utf8(buf, text_buf, len_utf8 + 1);
BLI_str_utf32_as_utf8(buf, text_buf, len_utf8 + 1);
WM_clipboard_text_set(buf, false);
MEM_freeN(buf);
}
@@ -1004,7 +1006,7 @@ void FONT_OT_text_cut(wmOperatorType *ot)
static bool paste_selection(Object *obedit, ReportList *reports)
{
wchar_t *text_buf;
char32_t *text_buf;
CharInfo *info_buf;
size_t len;
@@ -1024,7 +1026,7 @@ static int paste_text_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
int retval;
size_t len_utf8;
wchar_t *text_buf;
char32_t *text_buf;
/* Store both clipboards as utf8 for comparison,
* Give priority to the internal 'vfont' clipboard with its 'CharInfo' text styles
@@ -1050,7 +1052,7 @@ static int paste_text_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
BLI_strncpy_wchar_as_utf8(clipboard_vfont.buf, text_buf, len_utf8 + 1);
BLI_str_utf32_as_utf8(clipboard_vfont.buf, text_buf, len_utf8 + 1);
}
if (clipboard_vfont.buf && STREQ(clipboard_vfont.buf, clipboard_system.buf)) {
@@ -1164,7 +1166,7 @@ static int move_cursor(bContext *C, int type, const bool select)
case PREV_WORD: {
int pos = ef->pos;
BLI_str_cursor_step_wchar(
BLI_str_cursor_step_utf32(
ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
ef->pos = pos;
cursmove = FO_CURS;
@@ -1173,7 +1175,7 @@ static int move_cursor(bContext *C, int type, const bool select)
case NEXT_WORD: {
int pos = ef->pos;
BLI_str_cursor_step_wchar(
BLI_str_cursor_step_utf32(
ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
ef->pos = pos;
cursmove = FO_CURS;
@@ -1528,7 +1530,7 @@ static int delete_exec(bContext *C, wmOperator *op)
break;
case DEL_NEXT_WORD: {
int pos = ef->pos;
BLI_str_cursor_step_wchar(
BLI_str_cursor_step_utf32(
ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true);
range[0] = ef->pos;
range[1] = pos;
@@ -1537,7 +1539,7 @@ static int delete_exec(bContext *C, wmOperator *op)
case DEL_PREV_WORD: {
int pos = ef->pos;
BLI_str_cursor_step_wchar(
BLI_str_cursor_step_utf32(
ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true);
range[0] = pos;
range[1] = ef->pos;
@@ -1864,12 +1866,12 @@ void ED_curve_editfont_make(Object *obedit)
if (ef == NULL) {
ef = cu->editfont = MEM_callocN(sizeof(EditFont), "editfont");
ef->textbuf = MEM_callocN((MAXTEXT + 4) * sizeof(wchar_t), "texteditbuf");
ef->textbuf = MEM_callocN((MAXTEXT + 4) * sizeof(*ef->textbuf), "texteditbuf");
ef->textbufinfo = MEM_callocN((MAXTEXT + 4) * sizeof(CharInfo), "texteditbufinfo");
}
/* Convert the original text to wchar_t */
len_wchar = BLI_strncpy_wchar_from_utf8(ef->textbuf, cu->str, MAXTEXT + 4);
len_wchar = BLI_str_utf8_as_utf32(ef->textbuf, cu->str, MAXTEXT + 4);
BLI_assert(len_wchar == cu->len_wchar);
ef->len = len_wchar;
BLI_assert(ef->len >= 0);
@@ -1901,13 +1903,13 @@ void ED_curve_editfont_load(Object *obedit)
/* Calculate the actual string length in UTF-8 variable characters */
cu->len_wchar = ef->len;
cu->len = BLI_wstrlen_utf8(ef->textbuf);
cu->len = BLI_str_utf32_as_utf8_len(ef->textbuf);
/* Alloc memory for UTF-8 variable char length string */
cu->str = MEM_mallocN(cu->len + sizeof(wchar_t), "str");
cu->str = MEM_mallocN(cu->len + sizeof(char32_t), "str");
/* Copy the wchar to UTF-8 */
BLI_strncpy_wchar_as_utf8(cu->str, ef->textbuf, cu->len + 1);
BLI_str_utf32_as_utf8(cu->str, ef->textbuf, cu->len + 1);
if (cu->strinfo) {
MEM_freeN(cu->strinfo);
@@ -1943,7 +1945,7 @@ static int set_case(bContext *C, int ccase)
Object *obedit = CTX_data_edit_object(C);
Curve *cu = obedit->data;
EditFont *ef = cu->editfont;
wchar_t *str;
char32_t *str;
int len;
int selstart, selend;
@@ -2010,18 +2012,16 @@ static int toggle_case_exec(bContext *C, wmOperator *UNUSED(op))
Object *obedit = CTX_data_edit_object(C);
Curve *cu = obedit->data;
EditFont *ef = cu->editfont;
wchar_t *str;
int len, ccase = CASE_UPPER;
char32_t *str;
int ccase = CASE_UPPER;
len = wcslen(ef->textbuf);
str = ef->textbuf;
while (len) {
while (*str) {
if (*str >= 'a' && *str <= 'z') {
ccase = CASE_LOWER;
break;
}
len--;
str++;
}

View File

@@ -20,7 +20,6 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "MEM_guardedalloc.h"
@@ -58,7 +57,7 @@
* \{ */
typedef struct UndoFont {
wchar_t *textbuf;
char32_t *textbuf;
struct CharInfo *textbufinfo;
int len, pos, selstart, selend;
@@ -233,7 +232,7 @@ static void undofont_to_editfont(UndoFont *uf, Curve *cu)
uf_arraystore_expand(uf);
#endif
final_size = sizeof(wchar_t) * (uf->len + 1);
final_size = sizeof(*ef->textbuf) * (uf->len + 1);
memcpy(ef->textbuf, uf->textbuf, final_size);
final_size = sizeof(CharInfo) * (uf->len + 1);
@@ -259,7 +258,8 @@ static void *undofont_from_editfont(UndoFont *uf, Curve *cu)
size_t final_size;
final_size = sizeof(wchar_t) * (ef->len + 1);
BLI_assert(sizeof(*uf->textbuf) == sizeof(*ef->textbuf));
final_size = sizeof(*uf->textbuf) * (ef->len + 1);
uf->textbuf = MEM_mallocN(final_size, __func__);
memcpy(uf->textbuf, ef->textbuf, final_size);

View File

@@ -141,6 +141,12 @@ typedef enum eKeyframeIterFlags {
/* Perform NLA time remapping (global -> strip) for the "f2" parameter */
KED_F2_NLA_UNMAP = (1 << 2),
/* Set this when handles aren't visible by default and you want to perform additional checks to
* get the actual visibility state. E.g. in some cases handles are only drawn if either a handle
* or their control point is selected. The selection state will have to be checked in the
* iterator callbacks then. */
KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE = (1 << 3),
} eKeyframeIterFlags;
/* --- Generic Properties for Keyframe Edit Tools ----- */

View File

@@ -923,6 +923,7 @@ bool edit_modifier_poll_generic(bContext *C,
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C);
ModifierData *mod = ptr.data; /* May be NULL. */
if (!ob || ID_IS_LINKED(ob)) {
return 0;
@@ -935,8 +936,10 @@ bool edit_modifier_poll_generic(bContext *C,
}
if (ID_IS_OVERRIDE_LIBRARY(ob)) {
CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from library override");
return (((ModifierData *)ptr.data)->flag & eModifierFlag_OverrideLibrary_Local) != 0;
if ((mod != NULL) && (mod->flag & eModifierFlag_OverrideLibrary_Local) == 0) {
CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from library override");
return 0;
}
}
if (!is_editmode_allowed && CTX_data_edit_object(C) != NULL) {

View File

@@ -51,6 +51,7 @@ void CONSOLE_OT_delete(struct wmOperatorType *ot);
void CONSOLE_OT_insert(struct wmOperatorType *ot);
void CONSOLE_OT_indent(struct wmOperatorType *ot);
void CONSOLE_OT_indent_or_autocomplete(struct wmOperatorType *ot);
void CONSOLE_OT_unindent(struct wmOperatorType *ot);
void CONSOLE_OT_history_append(struct wmOperatorType *ot);

View File

@@ -473,6 +473,44 @@ void CONSOLE_OT_insert(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* -------------------------------------------------------------------- */
/** \name Indent or Autocomplete Operator
* \{ */
static int console_indent_or_autocomplete_exec(bContext *C, wmOperator *UNUSED(op))
{
ConsoleLine *ci = console_history_verify(C);
bool text_before_cursor = ci->cursor != 0 && !ELEM(ci->line[ci->cursor - 1], ' ', '\t');
if (text_before_cursor) {
WM_operator_name_call(C, "CONSOLE_OT_autocomplete", WM_OP_INVOKE_DEFAULT, NULL);
}
else {
WM_operator_name_call(C, "CONSOLE_OT_indent", WM_OP_EXEC_DEFAULT, NULL);
}
return OPERATOR_FINISHED;
}
void CONSOLE_OT_indent_or_autocomplete(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Indent or Autocomplete";
ot->idname = "CONSOLE_OT_indent_or_autocomplete";
ot->description = "Indent selected text or autocomplete";
/* api callbacks */
ot->exec = console_indent_or_autocomplete_exec;
ot->poll = ED_operator_console_active;
/* flags */
ot->flag = 0;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Indent Operator
* \{ */
static int console_indent_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceConsole *sc = CTX_wm_space_console(C);
@@ -518,6 +556,8 @@ void CONSOLE_OT_indent(wmOperatorType *ot)
ot->poll = ED_operator_console_active;
}
/** \} */
static int console_unindent_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceConsole *sc = CTX_wm_space_console(C);

View File

@@ -245,6 +245,7 @@ static void console_operatortypes(void)
WM_operatortype_append(CONSOLE_OT_insert);
WM_operatortype_append(CONSOLE_OT_indent);
WM_operatortype_append(CONSOLE_OT_indent_or_autocomplete);
WM_operatortype_append(CONSOLE_OT_unindent);
/* for use by python only */

View File

@@ -281,7 +281,7 @@ static void graphedit_activekey_handles_cb(bContext *C, void *fcu_ptr, void *bez
bezt->h2 = HD_ALIGN;
}
else {
BKE_nurb_bezt_handle_test(bezt, true);
BKE_nurb_bezt_handle_test(bezt, SELECT, true);
}
/* now call standard updates */

View File

@@ -552,6 +552,10 @@ static void box_select_graphkeys(bAnimContext *ac,
ked.data = &scaled_rectf;
}
if (sipo->flag & SIPO_SELVHANDLESONLY) {
ked.iterflags |= KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE;
}
/* treat handles separately? */
if (incl_handles) {
ked.iterflags |= KEYFRAME_ITER_INCL_HANDLES;
@@ -722,7 +726,7 @@ void GRAPH_OT_select_box(wmOperatorType *ot)
ot->prop = RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
RNA_def_boolean(ot->srna,
"include_handles",
0,
true,
"Include Handles",
"Are handles tested individually against the selection criteria");
@@ -1417,23 +1421,42 @@ void GRAPH_OT_select_leftright(wmOperatorType *ot)
*/
/* option 1) select keyframe directly under mouse */
static void mouse_graph_keys(bAnimContext *ac,
const int mval[2],
short select_mode,
const bool deselect_all,
const bool curves_only)
static int mouse_graph_keys(bAnimContext *ac,
const int mval[2],
eEditKeyframes_Select select_mode,
const bool deselect_all,
const bool curves_only,
bool wait_to_deselect_others)
{
SpaceGraph *sipo = (SpaceGraph *)ac->sl;
tNearestVertInfo *nvi;
BezTriple *bezt = NULL;
bool run_modal = false;
/* find the beztriple that we're selecting, and the handle that was clicked on */
nvi = find_nearest_fcurve_vert(ac, mval);
if (select_mode != SELECT_REPLACE) {
/* The modal execution to delay deselecting other items is only needed for normal click
* selection, i.e. for SELECT_REPLACE. */
wait_to_deselect_others = false;
}
sipo->runtime.flag &= ~(SIPO_RUNTIME_FLAG_TWEAK_HANDLES_LEFT |
SIPO_RUNTIME_FLAG_TWEAK_HANDLES_RIGHT);
const bool already_selected =
(nvi != NULL) && (((nvi->hpoint == NEAREST_HANDLE_KEY) && (nvi->bezt->f2 & SELECT)) ||
((nvi->hpoint == NEAREST_HANDLE_LEFT) && (nvi->bezt->f1 & SELECT)) ||
((nvi->hpoint == NEAREST_HANDLE_RIGHT) && (nvi->bezt->f3 & SELECT)));
if (wait_to_deselect_others && nvi && already_selected) {
run_modal = true;
}
/* For replacing selection, if we have something to select, we have to clear existing selection.
* The same goes if we found nothing to select, and deselect_all is true
* (deselect on nothing behavior). */
if ((nvi != NULL && select_mode == SELECT_REPLACE) || (nvi == NULL && deselect_all)) {
else if ((nvi != NULL && select_mode == SELECT_REPLACE) || (nvi == NULL && deselect_all)) {
/* reset selection mode */
select_mode = SELECT_ADD;
@@ -1450,7 +1473,7 @@ static void mouse_graph_keys(bAnimContext *ac,
}
if (nvi == NULL) {
return;
return deselect_all ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
/* if points can be selected on this F-Curve */
@@ -1461,17 +1484,9 @@ static void mouse_graph_keys(bAnimContext *ac,
bezt = nvi->bezt; /* used to check bezt seletion is set */
/* depends on selection mode */
if (select_mode == SELECT_INVERT) {
/* keyframe - invert select of all */
if (nvi->hpoint == NEAREST_HANDLE_KEY) {
if (BEZT_ISSEL_ANY(bezt)) {
BEZT_DESEL_ALL(bezt);
}
else {
BEZT_SEL_ALL(bezt);
}
bezt->f2 ^= SELECT;
}
/* handles - toggle selection of relevant handle */
else if (nvi->hpoint == NEAREST_HANDLE_LEFT) {
/* toggle selection */
bezt->f1 ^= SELECT;
@@ -1482,11 +1497,9 @@ static void mouse_graph_keys(bAnimContext *ac,
}
}
else {
/* if the keyframe was clicked on, select all verts of given beztriple */
if (nvi->hpoint == NEAREST_HANDLE_KEY) {
BEZT_SEL_ALL(bezt);
bezt->f2 |= SELECT;
}
/* otherwise, select the handle that applied */
else if (nvi->hpoint == NEAREST_HANDLE_LEFT) {
bezt->f1 |= SELECT;
}
@@ -1547,8 +1560,17 @@ static void mouse_graph_keys(bAnimContext *ac,
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, nvi->ctype);
}
if (nvi->hpoint == NEAREST_HANDLE_LEFT) {
sipo->runtime.flag |= SIPO_RUNTIME_FLAG_TWEAK_HANDLES_LEFT;
}
else if (nvi->hpoint == NEAREST_HANDLE_RIGHT) {
sipo->runtime.flag |= SIPO_RUNTIME_FLAG_TWEAK_HANDLES_RIGHT;
}
/* free temp sample data for filtering */
MEM_freeN(nvi);
return run_modal ? OPERATOR_RUNNING_MODAL : OPERATOR_FINISHED;
}
/* Option 2) Selects all the keyframes on either side of the current frame
@@ -1556,11 +1578,15 @@ static void mouse_graph_keys(bAnimContext *ac,
/* (see graphkeys_select_leftright) */
/* Option 3) Selects all visible keyframes in the same frame as the mouse click */
static void graphkeys_mselect_column(bAnimContext *ac, const int mval[2], short select_mode)
static int graphkeys_mselect_column(bAnimContext *ac,
const int mval[2],
eEditKeyframes_Select select_mode,
bool wait_to_deselect_others)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
bool run_modal = false;
KeyframeEditFunc select_cb, ok_cb;
KeyframeEditData ked;
@@ -1572,15 +1598,22 @@ static void graphkeys_mselect_column(bAnimContext *ac, const int mval[2], short
/* check if anything to select */
if (nvi == NULL) {
return;
return OPERATOR_CANCELLED;
}
/* get frame number on which elements should be selected */
// TODO: should we restrict to integer frames only?
selx = nvi->frame;
/* if select mode is replace, deselect all keyframes first */
if (select_mode == SELECT_REPLACE) {
if (select_mode != SELECT_REPLACE) {
/* Doesn't need to deselect anything -> Pass. */
}
else if (wait_to_deselect_others && (nvi->bezt->f2 & SELECT)) {
run_modal = true;
}
/* If select mode is replace (and we don't do delayed deselection on mouse release), deselect all
* keyframes first. */
else {
/* reset selection mode to add to selection */
select_mode = SELECT_ADD;
@@ -1622,12 +1655,14 @@ static void graphkeys_mselect_column(bAnimContext *ac, const int mval[2], short
MEM_freeN(nvi);
BLI_freelistN(&ked.list);
ANIM_animdata_freelist(&anim_data);
return run_modal ? OPERATOR_RUNNING_MODAL : OPERATOR_FINISHED;
}
/* ------------------- */
/* handle clicking */
static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int graphkeys_clickselect_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
@@ -1639,27 +1674,37 @@ static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEve
/* select mode is either replace (deselect all, then add) or add/extend */
const short selectmode = RNA_boolean_get(op->ptr, "extend") ? SELECT_INVERT : SELECT_REPLACE;
const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
/* See #WM_operator_properties_generic_select() for a detailed description of the how and why of
* this. */
const bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others");
int mval[2];
int ret_val;
mval[0] = RNA_int_get(op->ptr, "mouse_x");
mval[1] = RNA_int_get(op->ptr, "mouse_y");
/* figure out action to take */
if (RNA_boolean_get(op->ptr, "column")) {
/* select all keyframes in the same frame as the one that was under the mouse */
graphkeys_mselect_column(&ac, event->mval, selectmode);
ret_val = graphkeys_mselect_column(&ac, mval, selectmode, wait_to_deselect_others);
}
else if (RNA_boolean_get(op->ptr, "curves")) {
/* select all keyframes in the same F-Curve as the one under the mouse */
mouse_graph_keys(&ac, event->mval, selectmode, deselect_all, true);
ret_val = mouse_graph_keys(&ac, mval, selectmode, deselect_all, true, wait_to_deselect_others);
}
else {
/* select keyframe under mouse */
mouse_graph_keys(&ac, event->mval, selectmode, deselect_all, false);
ret_val = mouse_graph_keys(
&ac, mval, selectmode, deselect_all, false, wait_to_deselect_others);
}
/* set notifier that keyframe selection (and also channel selection in some cases) has changed */
/* set notifier that keyframe selection (and also channel selection in some cases) has
* changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL);
/* for tweak grab to work */
return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
return ret_val | OPERATOR_PASS_THROUGH;
}
void GRAPH_OT_clickselect(wmOperatorType *ot)
@@ -1672,19 +1717,22 @@ void GRAPH_OT_clickselect(wmOperatorType *ot)
ot->description = "Select keyframes by clicking on them";
/* callbacks */
ot->invoke = graphkeys_clickselect_invoke;
ot->poll = graphop_visible_keyframes_poll;
ot->exec = graphkeys_clickselect_exec;
ot->invoke = WM_generic_select_invoke;
ot->modal = WM_generic_select_modal;
/* flags */
ot->flag = OPTYPE_UNDO;
/* properties */
prop = RNA_def_boolean(
ot->srna,
"extend",
0,
"Extend Select",
"Toggle keyframe selection instead of leaving newly selected keyframes only"); // SHIFTKEY
WM_operator_properties_generic_select(ot);
prop = RNA_def_boolean(ot->srna,
"extend",
0,
"Extend Select",
"Toggle keyframe selection instead of leaving newly selected "
"keyframes only"); // SHIFTKEY
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean(ot->srna,
@@ -1694,12 +1742,12 @@ void GRAPH_OT_clickselect(wmOperatorType *ot)
"Deselect all when nothing under the cursor");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean(
ot->srna,
"column",
0,
"Column Select",
"Select all keyframes that occur on the same frame as the one under the mouse"); // ALTKEY
prop = RNA_def_boolean(ot->srna,
"column",
0,
"Column Select",
"Select all keyframes that occur on the same frame as the one under "
"the mouse"); // ALTKEY
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean(ot->srna,

View File

@@ -796,6 +796,9 @@ static void graph_refresh(const bContext *C, ScrArea *sa)
ED_area_tag_redraw(sa);
}
sipo->runtime.flag &= ~(SIPO_RUNTIME_FLAG_TWEAK_HANDLES_LEFT |
SIPO_RUNTIME_FLAG_TWEAK_HANDLES_RIGHT);
/* init/adjust F-Curve colors */
graph_refresh_fcurve_colors(C);
}

View File

@@ -203,6 +203,7 @@ static void text_operatortypes(void)
WM_operatortype_append(TEXT_OT_comment_toggle);
WM_operatortype_append(TEXT_OT_unindent);
WM_operatortype_append(TEXT_OT_indent);
WM_operatortype_append(TEXT_OT_indent_or_autocomplete);
WM_operatortype_append(TEXT_OT_select_line);
WM_operatortype_append(TEXT_OT_select_all);

View File

@@ -137,6 +137,7 @@ void TEXT_OT_convert_whitespace(struct wmOperatorType *ot);
void TEXT_OT_comment_toggle(struct wmOperatorType *ot);
void TEXT_OT_unindent(struct wmOperatorType *ot);
void TEXT_OT_indent(struct wmOperatorType *ot);
void TEXT_OT_indent_or_autocomplete(struct wmOperatorType *ot);
void TEXT_OT_line_break(struct wmOperatorType *ot);
void TEXT_OT_insert(struct wmOperatorType *ot);

View File

@@ -1068,6 +1068,41 @@ void TEXT_OT_cut(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Indent or Autocomplete Operator
* \{ */
static int text_indent_or_autocomplete_exec(bContext *C, wmOperator *UNUSED(op))
{
Text *text = CTX_data_edit_text(C);
TextLine *line = text->curl;
bool text_before_cursor = text->curc != 0 && !ELEM(line->line[text->curc - 1], ' ', '\t');
if (text_before_cursor && (txt_has_sel(text) == false)) {
WM_operator_name_call(C, "TEXT_OT_autocomplete", WM_OP_INVOKE_DEFAULT, NULL);
}
else {
WM_operator_name_call(C, "TEXT_OT_indent", WM_OP_EXEC_DEFAULT, NULL);
}
return OPERATOR_FINISHED;
}
void TEXT_OT_indent_or_autocomplete(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Indent or Autocomplete";
ot->idname = "TEXT_OT_indent_or_autocomplete";
ot->description = "Indent selected text or autocomplete";
/* api callbacks */
ot->exec = text_indent_or_autocomplete_exec;
ot->poll = text_edit_poll;
/* flags */
ot->flag = 0;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Indent Operator
* \{ */

View File

@@ -2359,6 +2359,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
/* Needed to translate tweak events to mouse buttons. */
t->launch_event = event ? WM_userdef_event_type_from_keymap_type(event->type) : -1;
t->is_launch_event_tweak = event ? ISTWEAK(event->type) : false;
/* XXX Remove this when wm_operator_call_internal doesn't use window->eventstate
* (which can have type = 0) */

View File

@@ -213,7 +213,8 @@ typedef struct TransData2D {
float ih1[2], ih2[2];
} TransData2D;
/** Used to store 2 handles for each #TransData in case the other handle wasn't selected. */
/** Used to store 2 handles for each #TransData in case the other handle wasn't selected. Also to
* unset temporary flags. */
typedef struct TransDataCurveHandleFlags {
char ih1, ih2;
char *h1, *h2;
@@ -631,6 +632,9 @@ typedef struct TransInfo {
/*************** NEW STUFF *********************/
/** event type used to launch transform. */
short launch_event;
/** Is the actual launch event a tweak event? (launch_event above is set to the corresponding
* mouse button then.) */
bool is_launch_event_tweak;
struct {
/** Orientation type when when we're not constrained.

View File

@@ -921,10 +921,17 @@ typedef struct tRetainedKeyframe {
size_t del_count; /* number of keyframes of this sort that have been deleted so far */
} tRetainedKeyframe;
/* Called during special_aftertrans_update to make sure selected keyframes replace
/**
* Called during special_aftertrans_update to make sure selected keyframes replace
* any other keyframes which may reside on that frame (that is not selected).
*
* \param sel_flag: The flag (bezt.f1/2/3) value to use to determine selection. Usually `SELECT`,
* but may want to use a different one at times (if caller does not operate on
* selection).
*/
static void posttrans_fcurve_clean(FCurve *fcu, const bool use_handle)
static void posttrans_fcurve_clean(FCurve *fcu,
const eBezTriple_Flag sel_flag,
const bool use_handle)
{
/* NOTE: We assume that all keys are sorted */
ListBase retained_keys = {NULL, NULL};
@@ -1036,7 +1043,7 @@ static void posttrans_fcurve_clean(FCurve *fcu, const bool use_handle)
}
/* 3) Recalculate handles */
testhandles_fcurve(fcu, use_handle);
testhandles_fcurve(fcu, sel_flag, use_handle);
/* cleanup */
BLI_freelistN(&retained_keys);
@@ -1064,11 +1071,11 @@ static void posttrans_action_clean(bAnimContext *ac, bAction *act)
if (adt) {
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
posttrans_fcurve_clean(ale->key_data, false); /* only use handles in graph editor */
posttrans_fcurve_clean(ale->key_data, SELECT, false); /* only use handles in graph editor */
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
}
else {
posttrans_fcurve_clean(ale->key_data, false); /* only use handles in graph editor */
posttrans_fcurve_clean(ale->key_data, SELECT, false); /* only use handles in graph editor */
}
}
@@ -1090,7 +1097,7 @@ typedef struct BeztMap {
/* This function converts an FCurve's BezTriple array to a BeztMap array
* NOTE: this allocates memory that will need to get freed later
*/
static BeztMap *bezt_to_beztmaps(BezTriple *bezts, int totvert, const short UNUSED(use_handle))
static BeztMap *bezt_to_beztmaps(BezTriple *bezts, int totvert)
{
BezTriple *bezt = bezts;
BezTriple *prevbezt = NULL;
@@ -1118,7 +1125,7 @@ static BeztMap *bezt_to_beztmaps(BezTriple *bezts, int totvert, const short UNUS
}
/* This function copies the code of sort_time_ipocurve, but acts on BeztMap structs instead */
static void sort_time_beztmaps(BeztMap *bezms, int totvert, const short UNUSED(use_handle))
static void sort_time_beztmaps(BeztMap *bezms, int totvert)
{
BeztMap *bezm;
int i, ok = 1;
@@ -1163,8 +1170,7 @@ static void sort_time_beztmaps(BeztMap *bezms, int totvert, const short UNUSED(u
}
/* This function firstly adjusts the pointers that the transdata has to each BezTriple */
static void beztmap_to_data(
TransInfo *t, FCurve *fcu, BeztMap *bezms, int totvert, const short UNUSED(use_handle))
static void beztmap_to_data(TransInfo *t, FCurve *fcu, BeztMap *bezms, int totvert)
{
BezTriple *bezts = fcu->bezt;
BeztMap *bezm;
@@ -1270,9 +1276,9 @@ void remake_graph_transdata(TransInfo *t, ListBase *anim_data)
/* adjust transform-data pointers */
/* note, none of these functions use 'use_handle', it could be removed */
bezm = bezt_to_beztmaps(fcu->bezt, fcu->totvert, use_handle);
sort_time_beztmaps(bezm, fcu->totvert, use_handle);
beztmap_to_data(t, fcu, bezm, fcu->totvert, use_handle);
bezm = bezt_to_beztmaps(fcu->bezt, fcu->totvert);
sort_time_beztmaps(bezm, fcu->totvert);
beztmap_to_data(t, fcu, bezm, fcu->totvert);
/* free mapping stuff */
MEM_freeN(bezm);
@@ -1281,7 +1287,7 @@ void remake_graph_transdata(TransInfo *t, ListBase *anim_data)
sort_time_fcurve(fcu);
/* make sure handles are all set correctly */
testhandles_fcurve(fcu, use_handle);
testhandles_fcurve(fcu, BEZT_FLAG_TEMP_TAG, use_handle);
}
}
}
@@ -1959,11 +1965,11 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
if (adt) {
ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
posttrans_fcurve_clean(fcu, false); /* only use handles in graph editor */
posttrans_fcurve_clean(fcu, SELECT, false); /* only use handles in graph editor */
ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
}
else {
posttrans_fcurve_clean(fcu, false); /* only use handles in graph editor */
posttrans_fcurve_clean(fcu, SELECT, false); /* only use handles in graph editor */
}
}
}
@@ -2103,11 +2109,11 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
if ((sipo->flag & SIPO_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
if (adt) {
ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
posttrans_fcurve_clean(fcu, use_handle);
posttrans_fcurve_clean(fcu, BEZT_FLAG_TEMP_TAG, use_handle);
ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
}
else {
posttrans_fcurve_clean(fcu, use_handle);
posttrans_fcurve_clean(fcu, BEZT_FLAG_TEMP_TAG, use_handle);
}
}
}

View File

@@ -1,4 +1,4 @@
/*
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -156,21 +156,55 @@ static bool graph_edit_use_local_center(TransInfo *t)
return ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (graph_edit_is_translation_mode(t) == false));
}
/**
* Get the effective selection of a triple for transform, i.e. return if the left handle, right
* handle and/or the center point should be affected by transform.
*/
static void graph_bezt_get_transform_selection(const TransInfo *t,
const BezTriple *bezt,
const bool use_handle,
bool *r_left_handle,
bool *r_key,
bool *r_right_handle)
{
SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
bool key = (bezt->f2 & SELECT) != 0;
bool left = use_handle ? ((bezt->f1 & SELECT) != 0) : key;
bool right = use_handle ? ((bezt->f3 & SELECT) != 0) : key;
if (use_handle && t->is_launch_event_tweak) {
if (sipo->runtime.flag & SIPO_RUNTIME_FLAG_TWEAK_HANDLES_LEFT) {
key = right = false;
}
else if (sipo->runtime.flag & SIPO_RUNTIME_FLAG_TWEAK_HANDLES_RIGHT) {
left = key = false;
}
}
/* Whenever we move the key, we also move both handles. */
if (key) {
left = right = true;
}
*r_key = key;
*r_left_handle = left;
*r_right_handle = right;
}
static void graph_key_shortest_dist(
TransInfo *t, FCurve *fcu, TransData *td_start, TransData *td, int cfra, bool use_handle)
{
int j = 0;
TransData *td_iter = td_start;
bool sel_key, sel_left, sel_right;
td->dist = FLT_MAX;
for (; j < fcu->totvert; j++) {
BezTriple *bezt = fcu->bezt + j;
if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
const bool sel2 = (bezt->f2 & SELECT) != 0;
const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right);
if (sel1 || sel2 || sel3) {
if (sel_left || sel_key || sel_right) {
td->dist = td->rdist = min_ff(td->dist, fabs(td_iter->center[0] - td->center[0]));
}
@@ -179,6 +213,15 @@ static void graph_key_shortest_dist(
}
}
/**
* It is important to note that this doesn't always act on the selection (like it's usually done),
* it acts on a subset of it. E.g. the selection code may leave a hint that we just dragged on a
* left or right handle (SIPO_RUNTIME_FLAG_TWEAK_HANDLES_LEFT/RIGHT) and then we only transform the
* selected left or right handles accordingly.
* The points to be transformed are tagged with BEZT_FLAG_TEMP_TAG; some lower level curve
* functions may need to be made aware of this. It's ugly that these act based on selection state
* anyway.
*/
void createTransGraphEditData(bContext *C, TransInfo *t)
{
SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
@@ -198,11 +241,11 @@ void createTransGraphEditData(bContext *C, TransInfo *t)
BezTriple *bezt;
int count = 0, i;
float mtx[3][3], smtx[3][3];
const bool is_translation_mode = graph_edit_is_translation_mode(t);
const bool use_handle = !(sipo->flag & SIPO_NOHANDLES);
const bool use_local_center = graph_edit_use_local_center(t);
const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
short anim_map_flag = ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS;
bool sel_key, sel_left, sel_right;
/* determine what type of data we are operating on */
if (ANIM_animdata_get_context(C, &ac) == 0) {
@@ -253,33 +296,29 @@ void createTransGraphEditData(bContext *C, TransInfo *t)
cfra = (float)CFRA;
}
/* Only include BezTriples whose 'keyframe'
* occurs on the same side of the current frame as mouse. */
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
/* Only include BezTriples whose 'keyframe'
* occurs on the same side of the current frame as mouse. */
if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
const bool sel2 = (bezt->f2 & SELECT) != 0;
const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right);
if (is_prop_edit) {
curvecount += 3;
if (sel2 || sel1 || sel3) {
if (sel_key || sel_left || sel_right) {
selected = true;
}
}
else {
if (!is_translation_mode || !(sel2)) {
if (sel1) {
count++;
}
if (sel_left) {
count++;
}
if (sel3) {
count++;
}
if (sel_right) {
count++;
}
/* only include main vert if selected */
if (sel2 && !use_local_center) {
if (sel_key && !use_local_center) {
count++;
}
}
@@ -366,19 +405,21 @@ void createTransGraphEditData(bContext *C, TransInfo *t)
unit_scale = ANIM_unit_mapping_get_factor(
ac.scene, ale->id, ale->key_data, anim_map_flag, &offset);
/* only include BezTriples whose 'keyframe' occurs on the same side
* of the current frame as mouse (if applicable) */
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
const bool sel2 = (bezt->f2 & SELECT) != 0;
const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
/* Ensure temp flag is cleared for all triples, we use it. */
bezt->f1 &= ~BEZT_FLAG_TEMP_TAG;
bezt->f2 &= ~BEZT_FLAG_TEMP_TAG;
bezt->f3 &= ~BEZT_FLAG_TEMP_TAG;
/* only include BezTriples whose 'keyframe' occurs on the same side
* of the current frame as mouse (if applicable) */
if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
TransDataCurveHandleFlags *hdata = NULL;
/* short h1=1, h2=1; */ /* UNUSED */
graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right);
if (is_prop_edit) {
bool is_sel = (sel2 || sel1 || sel3);
bool is_sel = (sel_key || sel_left || sel_right);
/* we always select all handles for proportional editing if central handle is selected */
initTransDataCurveHandles(td, bezt);
bezt_to_transdata(td++,
@@ -422,69 +463,69 @@ void createTransGraphEditData(bContext *C, TransInfo *t)
smtx,
unit_scale,
offset);
if (is_sel) {
bezt->f1 |= BEZT_FLAG_TEMP_TAG;
bezt->f2 |= BEZT_FLAG_TEMP_TAG;
bezt->f3 |= BEZT_FLAG_TEMP_TAG;
}
}
else {
/* only include handles if selected, irrespective of the interpolation modes.
* also, only treat handles specially if the center point isn't selected.
*/
if (!is_translation_mode || !(sel2)) {
if (sel1) {
hdata = initTransDataCurveHandles(td, bezt);
bezt_to_transdata(td++,
td2d++,
tdg++,
adt,
bezt,
0,
sel1,
true,
intvals,
mtx,
smtx,
unit_scale,
offset);
}
else {
/* h1 = 0; */ /* UNUSED */
}
if (sel_left) {
hdata = initTransDataCurveHandles(td, bezt);
bezt_to_transdata(td++,
td2d++,
tdg++,
adt,
bezt,
0,
sel_left,
true,
intvals,
mtx,
smtx,
unit_scale,
offset);
bezt->f1 |= BEZT_FLAG_TEMP_TAG;
}
if (sel3) {
if (hdata == NULL) {
hdata = initTransDataCurveHandles(td, bezt);
}
bezt_to_transdata(td++,
td2d++,
tdg++,
adt,
bezt,
2,
sel3,
true,
intvals,
mtx,
smtx,
unit_scale,
offset);
}
else {
/* h2 = 0; */ /* UNUSED */
if (sel_right) {
if (hdata == NULL) {
hdata = initTransDataCurveHandles(td, bezt);
}
bezt_to_transdata(td++,
td2d++,
tdg++,
adt,
bezt,
2,
sel_right,
true,
intvals,
mtx,
smtx,
unit_scale,
offset);
bezt->f3 |= BEZT_FLAG_TEMP_TAG;
}
/* only include main vert if selected */
if (sel2 && !use_local_center) {
if (sel_key && !use_local_center) {
/* move handles relative to center */
if (is_translation_mode) {
if (sel1) {
if (graph_edit_is_translation_mode(t)) {
if (sel_left) {
td->flag |= TD_MOVEHANDLE1;
}
if (sel3) {
if (sel_right) {
td->flag |= TD_MOVEHANDLE2;
}
}
/* if handles were not selected, store their selection status */
if (!(sel1) || !(sel3)) {
if (!(sel_left) || !(sel_right)) {
if (hdata == NULL) {
hdata = initTransDataCurveHandles(td, bezt);
}
@@ -496,13 +537,14 @@ void createTransGraphEditData(bContext *C, TransInfo *t)
adt,
bezt,
1,
sel2,
sel_key,
false,
intvals,
mtx,
smtx,
unit_scale,
offset);
bezt->f2 |= BEZT_FLAG_TEMP_TAG;
}
/* Special hack (must be done after #initTransDataCurveHandles(),
* as that stores handle settings to restore...):
@@ -513,7 +555,7 @@ void createTransGraphEditData(bContext *C, TransInfo *t)
*/
if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) && ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM) &&
ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) {
if (hdata && (sel1) && (sel3)) {
if (hdata && (sel_left) && (sel_right)) {
bezt->h1 = HD_ALIGN;
bezt->h2 = HD_ALIGN;
}
@@ -523,7 +565,7 @@ void createTransGraphEditData(bContext *C, TransInfo *t)
}
/* Sets handles based on the selection */
testhandles_fcurve(fcu, use_handle);
testhandles_fcurve(fcu, BEZT_FLAG_TEMP_TAG, use_handle);
}
if (is_prop_edit) {
@@ -551,15 +593,13 @@ void createTransGraphEditData(bContext *C, TransInfo *t)
cfra = (float)CFRA;
}
/* only include BezTriples whose 'keyframe' occurs on the
* same side of the current frame as mouse (if applicable) */
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
/* only include BezTriples whose 'keyframe' occurs on the
* same side of the current frame as mouse (if applicable) */
if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
const bool sel2 = (bezt->f2 & SELECT) != 0;
const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right);
if (sel1 || sel2) {
if (sel_left || sel_key) {
td->dist = td->rdist = 0.0f;
}
else {
@@ -567,7 +607,7 @@ void createTransGraphEditData(bContext *C, TransInfo *t)
}
td++;
if (sel2) {
if (sel_key) {
td->dist = td->rdist = 0.0f;
}
else {
@@ -575,7 +615,7 @@ void createTransGraphEditData(bContext *C, TransInfo *t)
}
td++;
if (sel3 || sel2) {
if (sel_right || sel_key) {
td->dist = td->rdist = 0.0f;
}
else {

View File

@@ -448,7 +448,7 @@ static void recalcData_graphedit(TransInfo *t)
dosort++;
}
else {
calchandles_fcurve(fcu);
calchandles_fcurve_ex(fcu, BEZT_FLAG_TEMP_TAG);
}
/* set refresh tags for objects using this animation,

View File

@@ -32,6 +32,7 @@ extern "C" {
#endif
struct FileData;
struct GHash;
struct GPUTexture;
struct ID;
struct Library;
@@ -206,6 +207,9 @@ typedef struct IDOverrideLibraryProperty {
ListBase operations;
} IDOverrideLibraryProperty;
/* We do not need a full struct for that currently, just a GHash. */
typedef struct GHash IDOverrideLibraryRuntime;
/* Main container for all overriding data info of a data-block. */
typedef struct IDOverrideLibrary {
/** Reference linked ID which this one overrides. */
@@ -220,6 +224,8 @@ typedef struct IDOverrideLibrary {
/* Temp ID storing extra override data (used for differential operations only currently).
* Always NULL outside of read/write context. */
struct ID *storage;
IDOverrideLibraryRuntime *runtime;
} IDOverrideLibrary;
enum eOverrideLibrary_Flag {

View File

@@ -483,6 +483,13 @@ typedef enum eGraphEdit_Runtime_Flag {
SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC = (1 << 0),
/** Temporary flag to force fcurves to recalculate colors. */
SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR = (1 << 1),
/**
* These flags are for the mouse-select code to communicate with the transform code. Click
* dragging (tweaking) a handle sets the according left/right flag which transform code uses then
* to limit translation to this side. */
SIPO_RUNTIME_FLAG_TWEAK_HANDLES_LEFT = (1 << 2),
SIPO_RUNTIME_FLAG_TWEAK_HANDLES_RIGHT = (1 << 3),
} eGraphEdit_Runtime_Flag;
/** \} */

View File

@@ -3604,7 +3604,7 @@ char *RNA_property_string_get_default_alloc(PointerRNA *ptr,
/* this is the length without \0 terminator */
int RNA_property_string_default_length(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
{
StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
StringPropertyRNA *sprop = (StringPropertyRNA *)rna_ensure_property(prop);
BLI_assert(RNA_property_type(prop) == PROP_STRING);

View File

@@ -27,6 +27,8 @@
#include "BLI_utildefines.h"
#include "BLI_string.h"
#define DEBUG_OVERRIDE_TIMEIT
#ifdef DEBUG_OVERRIDE_TIMEIT
# include "PIL_time_utildefines.h"
#endif

View File

@@ -585,7 +585,7 @@ static void rna_Curve_body_set(PointerRNA *ptr, const char *value)
MEM_freeN(cu->strinfo);
}
cu->str = MEM_mallocN(len_bytes + sizeof(wchar_t), "str");
cu->str = MEM_mallocN(len_bytes + sizeof(char32_t), "str");
cu->strinfo = MEM_callocN((len_chars + 4) * sizeof(CharInfo), "strinfo");
BLI_strncpy(cu->str, value, len_bytes + 1);

View File

@@ -396,8 +396,38 @@ void WM_operator_properties_select_operation_simple(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/**
* Selecting and tweaking items are overlapping operations. Getting both to work without conflicts
* requires special care. See
* https://wiki.blender.org/wiki/Human_Interface_Guidelines/Selection#Select-tweaking for the
* desired behavior.
*
* For default click selection (with no modifier keys held), the select operators can do the
* following:
* - On a mouse press on an unselected item, change selection and finish immidiately after.
* This sends an undo push and allows transform to take over should a tweak event be caught now.
* - On a mouse press on a selected item, don't change selection state, but start modal execution
* of the operator. Idea is that we wait with deselecting other items until we know that the
* intention wasn't to tweak (mouse press+drag) all selected items.
* - If a tweak is recognized before the release event happens, cancel the operator, so that
* transform can take over and no undo-push is sent.
* - If the release event occurs rather than a tweak one, deselect all items but the one under the
* cursor, and finish the modal operator.
*
* This utility, together with #WM_generic_select_invoke() and #WM_generic_select_modal() should
* help getting the wanted behavior to work. Most generic logic should be handled in these, so that
* the select operators only have to care for the case dependent handling.
*
* Every select operator has slightly diferent requirements, e.g. VSE strip selection also needs to
* account for handle selection. This should be the baseline behavior though.
*/
void WM_operator_properties_generic_select(wmOperatorType *ot)
{
/* On the initial mouse press, this is set by #WM_generic_select_modal() to let the select
* operator exec callback know that it should not __yet__ deselect other items when clicking on
* an already selected one. Instead should make sure the operator executes modal then (see
* #WM_generic_select_modal()), so that the exec callback can be called a second time on the
* mouse release event to do this part. */
PropertyRNA *prop = RNA_def_boolean(
ot->srna, "wait_to_deselect_others", false, "Wait to Deselect Others", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);

View File

@@ -721,6 +721,13 @@ void WM_operator_properties_free(PointerRNA *ptr)
/** \name Default Operator Callbacks
* \{ */
/**
* Helper to get select and tweak-transform to work conflict free and as desired. See
* #WM_operator_properties_generic_select() for details.
*
* To be used together with #WM_generic_select_invoke() and
* #WM_operator_properties_generic_select().
*/
int WM_generic_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
PropertyRNA *wait_to_deselect_prop = RNA_struct_find_property(op->ptr,
@@ -787,6 +794,13 @@ int WM_generic_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH;
}
/**
* Helper to get select and tweak-transform to work conflict free and as desired. See
* #WM_operator_properties_generic_select() for details.
*
* To be used together with #WM_generic_select_modal() and
* #WM_operator_properties_generic_select().
*/
int WM_generic_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
RNA_int_set(op->ptr, "mouse_x", event->mval[0]);