diff options
58 files changed, 1462 insertions, 846 deletions
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 570e0721268..9c59e1566a9 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -151,7 +151,7 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, instanced = true; else #endif - sd->object = -sd->object-1; + sd->object = ~sd->object; #ifdef __INSTANCING__ } #endif diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 74943fd0ff7..c8206365373 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -109,7 +109,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen /* triangles */ size_t offset = 0; - size_t j = 0; + int j = 0; foreach(Object *object, scene->objects) { Mesh *mesh = object->mesh; @@ -128,7 +128,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen /* sum area */ if(have_emission) { Transform tfm = object->tfm; - int object_id = (mesh->transform_applied)? -j-1: j; + int object_id = j; + + if(mesh->transform_applied) + object_id = ~object_id; for(size_t i = 0; i < mesh->triangles.size(); i++) { Shader *shader = scene->shaders[mesh->shader[i]]; @@ -161,9 +164,9 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen if(!multi_light) { float lightarea = (totarea > 0.0f)? totarea/scene->lights.size(): 1.0f; - for(size_t i = 0; i < scene->lights.size(); i++, offset++) { + for(int i = 0; i < scene->lights.size(); i++, offset++) { distribution[offset].x = totarea; - distribution[offset].y = __int_as_float(-i-1); + distribution[offset].y = __int_as_float(~(int)i); distribution[offset].z = 1.0f; distribution[offset].w = scene->lights[i]->size; totarea += lightarea; diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 4d2f41b48bd..3ec8d3d2fbf 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -68,13 +68,28 @@ class GHOST_IEventConsumer; * <li> Access to the state of the mouse buttons and the keyboard.</li> * <li> Menus for windows with events generated when they are accessed (this is * work in progress).</li> + * <li> Video mode switching.</li> + * <li> Copy/Paste buffers.</li> + * <li> System paths.</li> * </ul> * Font management has been moved to a separate library. * * \section platforms Platforms * + * GHOST supports the following platforms: + * <ul> + * <li> OSX Cocoa.</li> + * <li> OSX Carbon.</li> + * <li> Windows.</li> + * <li> X11.</li> + * <li> SDL1.3 (experemental).</li> + * <li> NULL (headless mode).</li> + * </ul> + * * \section Building GHOST * + * GHOST is not build standalone however there are tests in intern/ghost/test + * * \section interface Interface * GHOST has two programming interfaces: * <ul> diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index be5d45128f9..db4ed306dbe 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -137,6 +137,37 @@ static const NDOF_ButtonT SpacePilotPro_HID_map[] = { NDOF_BUTTON_MINUS }; +// latest HW: button-compatible with SpacePilotPro, just fewer of them +static const NDOF_ButtonT SpaceMousePro_HID_map[] = { + NDOF_BUTTON_MENU, + NDOF_BUTTON_FIT, + NDOF_BUTTON_TOP, + NDOF_BUTTON_NONE, // left + NDOF_BUTTON_RIGHT, + NDOF_BUTTON_FRONT, + NDOF_BUTTON_NONE, // bottom + NDOF_BUTTON_NONE, // back + NDOF_BUTTON_ROLL_CW, + NDOF_BUTTON_NONE, // roll ccw + NDOF_BUTTON_NONE, // iso 1 + NDOF_BUTTON_NONE, // iso 2 + NDOF_BUTTON_1, + NDOF_BUTTON_2, + NDOF_BUTTON_3, + NDOF_BUTTON_4, + NDOF_BUTTON_NONE, // 5 + NDOF_BUTTON_NONE, // 6 + NDOF_BUTTON_NONE, // 7 + NDOF_BUTTON_NONE, // 8 + NDOF_BUTTON_NONE, // 9 + NDOF_BUTTON_NONE, // 10 + NDOF_BUTTON_NONE, // esc key + NDOF_BUTTON_NONE, // alt key + NDOF_BUTTON_NONE, // shift key + NDOF_BUTTON_NONE, // ctrl key + NDOF_BUTTON_ROTATE, +}; + /* this is the older SpacePilot (sans Pro) * thanks to polosson for the info in this table */ static const NDOF_ButtonT SpacePilot_HID_map[] = { @@ -210,6 +241,12 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ m_deviceType = NDOF_SpacePilotPro; m_buttonCount = 31; break; + case 0xC62B: + puts("ndof: using SpaceMousePro"); + m_deviceType = NDOF_SpaceMousePro; + m_buttonCount = 27; + // ^^ actually has 15 buttons, but their HID codes range from 0 to 26 + break; // -- older devices -- case 0xC625: @@ -237,6 +274,8 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ else { m_buttonMask = ~(-1 << m_buttonCount); + // special case for SpaceMousePro? maybe... + #ifdef DEBUG_NDOF_BUTTONS printf("ndof: %d buttons -> hex:%X\n", m_buttonCount, m_buttonMask); #endif @@ -261,6 +300,16 @@ void GHOST_NDOFManager::updateRotation(short r[3], GHOST_TUns64 time) void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button, bool press, GHOST_TUns64 time, GHOST_IWindow* window) { + if (button == NDOF_BUTTON_NONE) { + // just being exceptionally cautious... + // air-tight button masking and proper function key emulation + // should guarantee we never get to this point +#ifdef DEBUG_NDOF_BUTTONS + printf("discarding NDOF_BUTTON_NONE (should not escape the NDOF manager)\n"); +#endif + return; + } + GHOST_EventNDOFButton* event = new GHOST_EventNDOFButton(time, window); GHOST_TEventNDOFButtonData* data = (GHOST_TEventNDOFButtonData*) event->getData(); @@ -317,6 +366,15 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 default: sendButtonEvent(SpacePilotPro_HID_map[button_number], press, time, window); } break; + case NDOF_SpaceMousePro: + switch (button_number) { + case 22: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break; + case 23: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break; + case 24: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break; + case 25: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break; + default: sendButtonEvent(SpaceMousePro_HID_map[button_number], press, time, window); + } + break; case NDOF_SpacePilot: switch (button_number) { case 10: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break; diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 34759035664..701f458ccf1 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -37,6 +37,7 @@ typedef enum { NDOF_SpaceNavigator, NDOF_SpaceExplorer, NDOF_SpacePilotPro, + NDOF_SpaceMousePro, // older devices NDOF_SpacePilot diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index de0cf641c2d..22c16009591 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -422,6 +422,18 @@ processEvents( return anyProcessed; } + +#ifdef WITH_X11_XINPUT +/* set currently using tablet mode (stylus or eraser) depending on device ID */ +static void setTabletMode(GHOST_WindowX11 * window, XID deviceid) +{ + if(deviceid == window->GetXTablet().StylusID) + window->GetXTablet().CommonData.Active= GHOST_kTabletModeStylus; + else if(deviceid == window->GetXTablet().EraserID) + window->GetXTablet().CommonData.Active= GHOST_kTabletModeEraser; +} +#endif /* WITH_X11_XINPUT */ + void GHOST_SystemX11::processEvent(XEvent *xe) { @@ -824,6 +836,12 @@ GHOST_SystemX11::processEvent(XEvent *xe) if(xe->type == window->GetXTablet().MotionEvent) { XDeviceMotionEvent* data = (XDeviceMotionEvent*)xe; + + /* stroke might begin without leading ProxyIn event, + * this happens when window is opened when stylus is already hovering + * around tablet surface */ + setTabletMode(window, data->deviceid); + window->GetXTablet().CommonData.Pressure= data->axis_data[2]/((float)window->GetXTablet().PressureLevels); @@ -837,10 +855,8 @@ GHOST_SystemX11::processEvent(XEvent *xe) else if(xe->type == window->GetXTablet().ProxInEvent) { XProximityNotifyEvent* data = (XProximityNotifyEvent*)xe; - if(data->deviceid == window->GetXTablet().StylusID) - window->GetXTablet().CommonData.Active= GHOST_kTabletModeStylus; - else if(data->deviceid == window->GetXTablet().EraserID) - window->GetXTablet().CommonData.Active= GHOST_kTabletModeEraser; + + setTabletMode(window, data->deviceid); } else if(xe->type == window->GetXTablet().ProxOutEvent) window->GetXTablet().CommonData.Active= GHOST_kTabletModeNone; diff --git a/intern/ghost/test/CMakeLists.txt b/intern/ghost/test/CMakeLists.txt index f834b55b387..75f082fe834 100644 --- a/intern/ghost/test/CMakeLists.txt +++ b/intern/ghost/test/CMakeLists.txt @@ -35,6 +35,25 @@ endmacro() # ----------------------------------------------------------------------------- +# Defines + +# set the endian define +if(MSVC) + # for some reason this fails on msvc + add_definitions(-D__LITTLE_ENDIAN__) +else() + include(TestBigEndian) + test_big_endian(_SYSTEM_BIG_ENDIAN) + if(_SYSTEM_BIG_ENDIAN) + add_definitions(-D__BIG_ENDIAN__) + else() + add_definitions(-D__LITTLE_ENDIAN__) + endif() + unset(_SYSTEM_BIG_ENDIAN) +endif() + + +# ----------------------------------------------------------------------------- # Libraries # ghost @@ -74,6 +93,7 @@ add_library(bli_lib "../../../source/blender/blenlib/intern/fileops.c" "../../../source/blender/blenlib/intern/rct.c" "../../../source/blender/blenlib/intern/string.c" + "../../../source/blender/blenlib/intern/string_utf8.c" "../../../source/blender/blenlib/intern/listbase.c" "../../../source/blender/blenlib/intern/storage.c" "../../../source/blender/blenlib/intern/path_util.c" @@ -87,6 +107,8 @@ find_package(OpenGL REQUIRED) find_package(Freetype REQUIRED) +find_package(ZLIB REQUIRED) + include_directories(${CMAKE_SOURCE_DIR}/../) include_directories(${OPENGL_INCLUDE_DIR}) include_directories(${FREETYPE_INCLUDE_DIRS}) @@ -151,5 +173,6 @@ target_link_libraries(multitest_c ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ${FREETYPE_LIBRARY} + ${ZLIB_LIBRARIES} ${PLATFORM_LINKLIBS} ) diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 2f80f674d84..eb7d6d76017 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -663,5 +663,10 @@ void DM_calc_auto_bump_scale(DerivedMesh *dm); /* Set object's bounding box based on DerivedMesh min/max data */ void DM_set_object_boundbox(struct Object *ob, DerivedMesh *dm); +/* debug only */ +#ifndef NDEBUG +char *DM_debug_info(DerivedMesh *dm); +void DM_debug_print(DerivedMesh *dm); #endif +#endif diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index c829fc69b05..5cdc3537f5b 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -186,7 +186,7 @@ void BKE_image_merge(struct Image *dest, struct Image *source); int BKE_image_has_alpha(struct Image *image); /* image_gen.c */ -void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, int height, float color[4]); +void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, int height, const float color[4]); void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int height, int width); void BKE_image_buf_fill_checker_color(unsigned char *rect, float *rect_float, int height, int width); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index a2aa1476c2b..63605c14f6c 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2739,3 +2739,84 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm) #endif /* WITH_GAMEENGINE */ /* --- NAVMESH (end) --- */ + + +/* derivedmesh info printing function, + * to help track down differences DM output */ + +#ifndef NDEBUG +#include "BLI_dynstr.h" + +static void dm_debug_info_layers(DynStr *dynstr, DerivedMesh *dm, void *(*getElemDataArray)(DerivedMesh *, int)) +{ + int type; + + for (type = 0; type < CD_NUMTYPES; type++) { + /* note: doesnt account for multiple layers */ + void *pt = getElemDataArray(dm, type); + if (pt) { + const char *name = CustomData_layertype_name(type); + const int size = CustomData_sizeof(type); + const char *structname; + int structnum; + CustomData_file_write_info(type, &structname, &structnum); + BLI_dynstr_appendf(dynstr, + " dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n", + name, structname, type, (void *)pt, size, (int)(MEM_allocN_len(pt) / size)); + } + } +} + +char *DM_debug_info(DerivedMesh *dm) +{ + DynStr *dynstr= BLI_dynstr_new(); + char *ret; + const char *tstr; + + BLI_dynstr_appendf(dynstr, "{\n"); + BLI_dynstr_appendf(dynstr, " 'ptr': '%p',\n", (void *)dm); + switch (dm->type) { + case DM_TYPE_CDDM: tstr = "DM_TYPE_CDDM"; break; + case DM_TYPE_EDITBMESH: tstr = "DM_TYPE_EDITMESH"; break; + case DM_TYPE_CCGDM: tstr = "DM_TYPE_CCGDM"; break; + default: tstr = "UNKNOWN"; break; + } + BLI_dynstr_appendf(dynstr, " 'type': '%s',\n", tstr); + BLI_dynstr_appendf(dynstr, " 'numVertData': %d,\n", dm->numVertData); + BLI_dynstr_appendf(dynstr, " 'numEdgeData': %d,\n", dm->numEdgeData); + BLI_dynstr_appendf(dynstr, " 'numTessFaceData': %d,\n", dm->numTessFaceData); + BLI_dynstr_appendf(dynstr, " 'numPolyData': %d,\n", dm->numPolyData); + BLI_dynstr_appendf(dynstr, " 'deformedOnly': %d,\n", dm->deformedOnly); + + BLI_dynstr_appendf(dynstr, " 'vertexLayers': (\n"); + dm_debug_info_layers(dynstr, dm, dm->getVertDataArray); + BLI_dynstr_appendf(dynstr, " ),\n"); + + BLI_dynstr_appendf(dynstr, " 'edgeLayers': (\n"); + dm_debug_info_layers(dynstr, dm, dm->getEdgeDataArray); + BLI_dynstr_appendf(dynstr, " ),\n"); + + BLI_dynstr_appendf(dynstr, " 'tessFaceLayers': (\n"); + dm_debug_info_layers(dynstr, dm, dm->getTessFaceDataArray); + BLI_dynstr_appendf(dynstr, " ),\n"); + + BLI_dynstr_appendf(dynstr, " 'PolyLayers': (\n"); + dm_debug_info_layers(dynstr, dm, DM_get_poly_data_layer); + BLI_dynstr_appendf(dynstr, " ),\n"); + + BLI_dynstr_appendf(dynstr, "}\n"); + + ret = BLI_dynstr_get_cstring(dynstr); + BLI_dynstr_free(dynstr); + return ret; +} + +void DM_debug_print(DerivedMesh *dm) +{ + char *str = DM_debug_info(dm); + printf("%s", str); + fflush(stdout); + MEM_freeN(str); +} + +#endif /* NDEBUG */ diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 362fa6e5e9a..f2514c1030b 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -527,7 +527,7 @@ void brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texfall, float xy[2], rgba[4], *dstf; int x, y, rowbytes, xoff, yoff, imbflag; const int radius= brush_size(scene, brush); - char *dst, crgb[3]; + unsigned char *dst, crgb[3]; const float alpha= brush_alpha(scene, brush); float brush_rgb[3]; @@ -571,10 +571,10 @@ void brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texfall, } else { float alpha_f; /* final float alpha to convert to char */ - F3TOCHAR3(brush->rgb, crgb); + rgb_float_to_uchar(crgb, brush->rgb); for (y=0; y < ibuf->y; y++) { - dst = (char*)ibuf->rect + y*rowbytes; + dst = (unsigned char *)ibuf->rect + y*rowbytes; for (x=0; x < ibuf->x; x++, dst+=4) { xy[0] = x + xoff; @@ -590,19 +590,15 @@ void brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texfall, } else if (texfall == 1) { brush_sample_tex(scene, brush, xy, rgba, 0); - dst[0] = FTOCHAR(rgba[0]); - dst[1] = FTOCHAR(rgba[1]); - dst[2] = FTOCHAR(rgba[2]); - dst[3] = FTOCHAR(rgba[3]); + rgba_float_to_uchar(dst, rgba); } else if (texfall == 2) { brush_sample_tex(scene, brush, xy, rgba, 0); mul_v3_v3(rgba, brush->rgb); alpha_f = rgba[3] * alpha * brush_curve_strength_clamp(brush, len_v2(xy), radius); - dst[0] = FTOCHAR(rgba[0]); - dst[1] = FTOCHAR(rgba[1]); - dst[2] = FTOCHAR(rgba[2]); + rgb_float_to_uchar(dst, rgba); + dst[3] = FTOCHAR(alpha_f); } else { @@ -843,7 +839,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i Brush *brush= painter->brush; ImBuf *ibuf, *maskibuf, *texibuf; float *bf, *mf, *tf, *otf=NULL, xoff, yoff, xy[2], rgba[4]; - char *b, *m, *t, *ot= NULL; + unsigned char *b, *m, *t, *ot= NULL; int dotexold, origx= x, origy= y; const int radius= brush_size(painter->scene, brush); @@ -895,12 +891,12 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i } else { for (; y < h; y++) { - b = (char*)ibuf->rect + (y*ibuf->x + origx)*4; - t = (char*)texibuf->rect + (y*texibuf->x + origx)*4; - m = (char*)maskibuf->rect + (y*maskibuf->x + origx)*4; + b = (unsigned char *)ibuf->rect + (y*ibuf->x + origx)*4; + t = (unsigned char *)texibuf->rect + (y*texibuf->x + origx)*4; + m = (unsigned char *)maskibuf->rect + (y*maskibuf->x + origx)*4; if (dotexold) - ot = (char*)oldtexibuf->rect + ((y - origy + yt)*oldtexibuf->x + xt)*4; + ot = (unsigned char *)oldtexibuf->rect + ((y - origy + yt)*oldtexibuf->x + xt)*4; for (x=origx; x < w; x++, b+=4, m+=4, t+=4) { if (dotexold) { @@ -915,10 +911,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i xy[1] = y + yoff; brush_sample_tex(scene, brush, xy, rgba, 0); - t[0]= FTOCHAR(rgba[0]); - t[1]= FTOCHAR(rgba[1]); - t[2]= FTOCHAR(rgba[2]); - t[3]= FTOCHAR(rgba[3]); + rgba_float_to_uchar(t, rgba); } b[0] = t[0]*m[0]/255; diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c index a93d0221cf0..c6cb8c9582a 100644 --- a/source/blender/blenkernel/intern/image_gen.c +++ b/source/blender/blenkernel/intern/image_gen.c @@ -33,7 +33,7 @@ #include "BLI_math_base.h" #include "BLF_api.h" -void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, int height, float color[4]) +void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, int height, const float color[4]) { int x, y; @@ -41,22 +41,17 @@ void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, if(rect_float) { for(y= 0; y<height; y++) { for(x= 0; x<width; x++) { - rect_float[0]= color[0]; - rect_float[1]= color[1]; - rect_float[2]= color[2]; - rect_float[3]= color[3]; + copy_v4_v4(rect_float, color); rect_float+= 4; } } } if(rect) { - char ccol[4]; + unsigned char ccol[4]; + + rgba_float_to_uchar(ccol, color); - ccol[0]= (char)(color[0]*255.0f); - ccol[1]= (char)(color[1]*255.0f); - ccol[2]= (char)(color[2]*255.0f); - ccol[3]= (char)(color[3]*255.0f); for(y= 0; y<height; y++) { for(x= 0; x<width; x++) { diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 359470eecf2..a2d7d9b502c 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -790,16 +790,11 @@ void nodeAddToPreview(bNode *node, float *col, int x, int y, int do_manage) unsigned char *tar= preview->rect+ 4*((preview->xsize*y) + x); if(do_manage) { - tar[0]= FTOCHAR(linearrgb_to_srgb(col[0])); - tar[1]= FTOCHAR(linearrgb_to_srgb(col[1])); - tar[2]= FTOCHAR(linearrgb_to_srgb(col[2])); + linearrgb_to_srgb_uchar4(tar, col); } else { - tar[0]= FTOCHAR(col[0]); - tar[1]= FTOCHAR(col[1]); - tar[2]= FTOCHAR(col[2]); + rgba_float_to_uchar(tar, col); } - tar[3]= FTOCHAR(col[3]); } //else printf("prv out bound x y %d %d\n", x, y); } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 71377799651..08b53115919 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1690,10 +1690,10 @@ static ImBuf * input_preprocess( if(rct) { float rgb[3]; for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) { - rgb_byte_to_float(rct, rgb); + rgb_uchar_to_float(rgb, rct); rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2); hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rgb, rgb+1, rgb+2); - rgb_float_to_byte(rgb, rct); + rgb_float_to_uchar(rct, rgb); } } diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 6d37aabd6ab..453f1258272 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -101,8 +101,10 @@ void minmax_rgb(short c[3]); void rgb_float_set_hue_float_offset(float * rgb, float hue_offset); void rgb_byte_set_hue_float_offset(unsigned char * rgb, float hue_offset); -void rgb_byte_to_float(const unsigned char in[3], float out[3]); -void rgb_float_to_byte(const float in[3], unsigned char out[3]); +void rgb_uchar_to_float(float col_r[3], const unsigned char col_ub[3]); +void rgba_uchar_to_float(float col_r[4], const unsigned char col_ub[4]); +void rgb_float_to_uchar(unsigned char col_r[3], const float col_f[3]); +void rgba_float_to_uchar(unsigned char col_r[4], const float col_f[4]); /***************** lift/gamma/gain / ASC-CDL conversion *****************/ diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index 20df893015d..94dbdf9fe58 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -337,24 +337,47 @@ void cpack_to_rgb(unsigned int col, float *r, float *g, float *b) *b /= 255.0f; } -void rgb_byte_to_float(const unsigned char in[3], float out[3]) +void rgb_uchar_to_float(float col_r[3], const unsigned char col_ub[3]) { - out[0]= ((float)in[0]) / 255.0f; - out[1]= ((float)in[1]) / 255.0f; - out[2]= ((float)in[2]) / 255.0f; + col_r[0]= ((float)col_ub[0]) / 255.0f; + col_r[1]= ((float)col_ub[1]) / 255.0f; + col_r[2]= ((float)col_ub[2]) / 255.0f; } -void rgb_float_to_byte(const float in[3], unsigned char out[3]) +void rgba_uchar_to_float(float col_r[4], const unsigned char col_ub[4]) +{ + col_r[0]= ((float)col_ub[0]) / 255.0f; + col_r[1]= ((float)col_ub[1]) / 255.0f; + col_r[2]= ((float)col_ub[2]) / 255.0f; + col_r[3]= ((float)col_ub[3]) / 255.0f; +} + +void rgb_float_to_uchar(unsigned char col_r[3], const float col_f[3]) { int r, g, b; - r= (int)(in[0] * 255.0f); - g= (int)(in[1] * 255.0f); - b= (int)(in[2] * 255.0f); + r= (int)(col_f[0] * 255.0f); + g= (int)(col_f[1] * 255.0f); + b= (int)(col_f[2] * 255.0f); - out[0]= (char)((r <= 0)? 0 : (r >= 255)? 255 : r); - out[1]= (char)((g <= 0)? 0 : (g >= 255)? 255 : g); - out[2]= (char)((b <= 0)? 0 : (b >= 255)? 255 : b); + col_r[0]= (char)((r <= 0)? 0 : (r >= 255)? 255 : r); + col_r[1]= (char)((g <= 0)? 0 : (g >= 255)? 255 : g); + col_r[2]= (char)((b <= 0)? 0 : (b >= 255)? 255 : b); +} + +void rgba_float_to_uchar(unsigned char col_r[4], const float col_f[4]) +{ + int r, g, b, a; + + r= (int)(col_f[0] * 255.0f); + g= (int)(col_f[1] * 255.0f); + b= (int)(col_f[2] * 255.0f); + a= (int)(col_f[3] * 255.0f); + + col_r[0]= (char)((r <= 0)? 0 : (r >= 255)? 255 : r); + col_r[1]= (char)((g <= 0)? 0 : (g >= 255)? 255 : g); + col_r[2]= (char)((b <= 0)? 0 : (b >= 255)? 255 : b); + col_r[3]= (char)((a <= 0)? 0 : (a >= 255)? 255 : a); } /* ********************************* color transforms ********************************* */ @@ -490,9 +513,9 @@ void rgb_byte_set_hue_float_offset(unsigned char rgb[3], float hue_offset) { float rgb_float[3]; - rgb_byte_to_float(rgb, rgb_float); + rgb_uchar_to_float(rgb_float, rgb); rgb_float_set_hue_float_offset(rgb_float, hue_offset); - rgb_float_to_byte(rgb_float, rgb); + rgb_float_to_uchar(rgb, rgb_float); } diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c index 1247632cf79..2c7b13b86a2 100644 --- a/source/blender/blenlib/intern/math_color_inline.c +++ b/source/blender/blenlib/intern/math_color_inline.c @@ -62,6 +62,34 @@ MINLINE void linearrgb_to_srgb_v4(float srgb[4], const float linear[4]) srgb[3] = linear[3]; } +MINLINE void linearrgb_to_srgb_uchar3(unsigned char srgb[4], const float linear[4]) +{ + int r, g, b; + + r = 255 * linearrgb_to_srgb(linear[0]); + g = 255 * linearrgb_to_srgb(linear[1]); + b = 255 * linearrgb_to_srgb(linear[2]); + + srgb[0] = FTOCHAR(r); + srgb[1] = FTOCHAR(g); + srgb[2] = FTOCHAR(b); +} + +MINLINE void linearrgb_to_srgb_uchar4(unsigned char srgb[4], const float linear[4]) +{ + int r, g, b, a; + + r = 255 * linearrgb_to_srgb(linear[0]); + g = 255 * linearrgb_to_srgb(linear[1]); + b = 255 * linearrgb_to_srgb(linear[2]); + a = 255 * linear[3]; + + srgb[0] = FTOCHAR(r); + srgb[1] = FTOCHAR(g); + srgb[2] = FTOCHAR(b); + srgb[3] = FTOCHAR(a); +} + /* predivide versions to work on associated/premultipled alpha. if this should be done or not depends on the background the image will be composited over, ideally you would never do color space conversion on an image with alpha diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index f0f3b8f4123..a0082b3258f 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -186,7 +186,7 @@ static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, floa } /* copy the colors over, transforming from bytes to floats */ - rgb_byte_to_float(cp, color); + rgb_uchar_to_float(color, cp); } else { // FIXME: what happens when the indention is 1 greater than what it should be (due to grouping)? diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 852b030c0d2..6e921a0ca8c 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -45,79 +45,10 @@ typedef enum { } BIFIconID; #define BIFICONID_FIRST (ICON_NONE) -#define BIFNICONIDS (BIFICONID_LAST-BIFICONID_FIRST + 1) #undef DEF_ICON #undef DEF_VICO - -typedef enum { -#define BIFCOLORSHADE_FIRST (COLORSHADE_DARK) - COLORSHADE_DARK, - COLORSHADE_GREY, - COLORSHADE_MEDIUM, - COLORSHADE_HILITE, - COLORSHADE_LIGHT, - COLORSHADE_WHITE -#define BIFCOLORSHADE_LAST (COLORSHADE_WHITE) -#define BIFNCOLORSHADES (BIFCOLORSHADE_LAST-BIFCOLORSHADE_FIRST + 1) -} BIFColorShade; - -typedef enum { -#define BIFCOLORID_FIRST (BUTGREY) - BUTGREY = 0, - BUTGREEN, - BUTBLUE, - BUTSALMON, - MIDGREY, - BUTPURPLE, - BUTYELLOW, - REDALERT, - BUTRUST, - BUTWHITE, - BUTDBLUE, - BUTPINK, - BUTDPINK, - BUTMACTIVE, - - BUTIPO, - BUTAUDIO, - BUTCAMERA, - BUTRANDOM, - BUTEDITOBJECT, - BUTPROPERTY, - BUTSCENE, - BUTMOTION, - BUTMESSAGE, - BUTACTION, - BUTCD, - BUTGAME, - BUTVISIBILITY, - BUTYUCK, - BUTSEASICK, - BUTCHOKE, - BUTIMPERIAL, - - BUTTEXTCOLOR, - BUTTEXTPRESSED, - BUTSBACKGROUND, - - VIEWPORTBACKCOLOR, - VIEWPORTGRIDCOLOR, - VIEWPORTACTIVECOLOR, - VIEWPORTSELECTEDCOLOR, - VIEWPORTUNSELCOLOR, - - EDITVERTSEL, - EDITVERTUNSEL, - EDITEDGESEL, - EDITEDGEUNSEL - -#define BIFCOLORID_LAST (EDITEDGEUNSEL) -#define BIFNCOLORIDS (BIFCOLORID_LAST-BIFCOLORID_FIRST + 1) - -} BIFColorID; - enum { TH_REDALERT, diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index e31d7e39d89..7d53e7acbc2 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -163,7 +163,7 @@ struct uiBut { float hardmin, hardmax, softmin, softmax; float a1, a2; float aspect; - char col[4]; + unsigned char col[4]; uiButHandleFunc func; void *func_arg1; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 730254bba79..c8361f56fee 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2626,9 +2626,7 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) uiBlockBeginAlign(block); but= uiDefBut(block, ROUNDBOX, 0, "", 0, 0, UI_UNIT_X+10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); /* set the report's bg color in but->col - ROUNDBOX feature */ - but->col[0]= FTOCHAR(rti->col[0]); - but->col[1]= FTOCHAR(rti->col[1]); - but->col[2]= FTOCHAR(rti->col[2]); + rgb_float_to_uchar(but->col, rti->col); but->col[3]= 255; but= uiDefBut(block, ROUNDBOX, 0, "", UI_UNIT_X+10, 0, UI_UNIT_X+width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index f5c62f65512..19acfaccaa3 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2501,7 +2501,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat if (color_profile) linearrgb_to_srgb_v3_v3(col, col); - F4TOCHAR4(col, wcol->inner); + rgba_float_to_uchar((unsigned char *)wcol->inner, col); wcol->shaded = 0; wcol->alpha_check = (wcol->inner[3] < 255); diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index c3c3f91e37d..e7ab823fc99 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -807,10 +807,8 @@ static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, ibuf->userflags= IB_RECT_INVALID; } else { - char *rrgb= (char*)ibuf->rect + pixel*4; - rrgb[0]= FTOCHAR(vec[0]); - rrgb[1]= FTOCHAR(vec[1]); - rrgb[2]= FTOCHAR(vec[2]); + unsigned char *rrgb= (unsigned char *)ibuf->rect + pixel*4; + rgb_float_to_uchar(rrgb, vec); rrgb[3]= 255; } } diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt index 29e97c77bec..8a6a236d10f 100644 --- a/source/blender/editors/sculpt_paint/CMakeLists.txt +++ b/source/blender/editors/sculpt_paint/CMakeLists.txt @@ -39,6 +39,7 @@ set(INC_SYS ) set(SRC + paint_cursor.c paint_image.c paint_ops.c paint_stroke.c diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c new file mode 100644 index 00000000000..0148f11b930 --- /dev/null +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -0,0 +1,607 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2009 by Nicholas Bishop + * All rights reserved. + * + * Contributor(s): Jason Wilkins, Tom Musgrove. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +/** \file blender/editors/sculpt_paint/paint_cursor.c + * \ingroup edsculpt + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "DNA_brush_types.h" +#include "DNA_color_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_userdef_types.h" + +#include "BKE_brush.h" +#include "BKE_context.h" +#include "BKE_paint.h" + +#include "WM_api.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "ED_view3d.h" + +#include "paint_intern.h" +/* still needed for sculpt_stroke_get_location, should be + removed eventually (TODO) */ +#include "sculpt_intern.h" + +/* TODOs: + + Some of the cursor drawing code is doing non-draw stuff + (e.g. updating the brush rake angle). This should be cleaned up + still. + + There is also some ugliness with sculpt-specific code. + */ + +typedef struct Snapshot { + float size[3]; + float ofs[3]; + float rot; + int brush_size; + int winx; + int winy; + int brush_map_mode; + int curve_changed_timestamp; +} Snapshot; + +static int same_snap(Snapshot* snap, Brush* brush, ViewContext* vc) +{ + MTex* mtex = &brush->mtex; + + return (((mtex->tex) && + equals_v3v3(mtex->ofs, snap->ofs) && + equals_v3v3(mtex->size, snap->size) && + mtex->rot == snap->rot) && + + /* make brush smaller shouldn't cause a resample */ + ((mtex->brush_map_mode == MTEX_MAP_MODE_FIXED && + (brush_size(vc->scene, brush) <= snap->brush_size)) || + (brush_size(vc->scene, brush) == snap->brush_size)) && + + (mtex->brush_map_mode == snap->brush_map_mode) && + (vc->ar->winx == snap->winx) && + (vc->ar->winy == snap->winy)); +} + +static void make_snap(Snapshot* snap, Brush* brush, ViewContext* vc) +{ + if (brush->mtex.tex) { + snap->brush_map_mode = brush->mtex.brush_map_mode; + copy_v3_v3(snap->ofs, brush->mtex.ofs); + copy_v3_v3(snap->size, brush->mtex.size); + snap->rot = brush->mtex.rot; + } + else { + snap->brush_map_mode = -1; + snap->ofs[0]= snap->ofs[1]= snap->ofs[2]= -1; + snap->size[0]= snap->size[1]= snap->size[2]= -1; + snap->rot = -1; + } + + snap->brush_size = brush_size(vc->scene, brush); + snap->winx = vc->ar->winx; + snap->winy = vc->ar->winy; +} + +static int load_tex(Sculpt *sd, Brush* br, ViewContext* vc) +{ + static GLuint overlay_texture = 0; + static int init = 0; + static int tex_changed_timestamp = -1; + static int curve_changed_timestamp = -1; + static Snapshot snap; + static int old_size = -1; + + GLubyte* buffer = NULL; + + int size; + int j; + int refresh; + +#ifndef _OPENMP + (void)sd; /* quied unused warning */ +#endif + + if (br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED && !br->mtex.tex) return 0; + + refresh = + !overlay_texture || + (br->mtex.tex && + (!br->mtex.tex->preview || + br->mtex.tex->preview->changed_timestamp[0] != tex_changed_timestamp)) || + !br->curve || + br->curve->changed_timestamp != curve_changed_timestamp || + !same_snap(&snap, br, vc); + + if (refresh) { + if (br->mtex.tex && br->mtex.tex->preview) + tex_changed_timestamp = br->mtex.tex->preview->changed_timestamp[0]; + + if (br->curve) + curve_changed_timestamp = br->curve->changed_timestamp; + + make_snap(&snap, br, vc); + + if (br->mtex.brush_map_mode == MTEX_MAP_MODE_FIXED) { + int s = brush_size(vc->scene, br); + int r = 1; + + for (s >>= 1; s > 0; s >>= 1) + r++; + + size = (1<<r); + + if (size < 256) + size = 256; + + if (size < old_size) + size = old_size; + } + else + size = 512; + + if (old_size != size) { + if (overlay_texture) { + glDeleteTextures(1, &overlay_texture); + overlay_texture = 0; + } + + init = 0; + + old_size = size; + } + + buffer = MEM_mallocN(sizeof(GLubyte)*size*size, "load_tex"); + + #pragma omp parallel for schedule(static) if (sd->flags & SCULPT_USE_OPENMP) + for (j= 0; j < size; j++) { + int i; + float y; + float len; + + for (i= 0; i < size; i++) { + + // largely duplicated from tex_strength + + const float rotation = -br->mtex.rot; + float radius = brush_size(vc->scene, br); + int index = j*size + i; + float x; + float avg; + + x = (float)i/size; + y = (float)j/size; + + x -= 0.5f; + y -= 0.5f; + + if (br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED) { + x *= vc->ar->winx / radius; + y *= vc->ar->winy / radius; + } + else { + x *= 2; + y *= 2; + } + + len = sqrtf(x*x + y*y); + + if ((br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED) || len <= 1) { + /* it is probably worth optimizing for those cases where + the texture is not rotated by skipping the calls to + atan2, sqrtf, sin, and cos. */ + if (br->mtex.tex && (rotation > 0.001f || rotation < -0.001f)) { + const float angle = atan2f(y, x) + rotation; + + x = len * cosf(angle); + y = len * sinf(angle); + } + + x *= br->mtex.size[0]; + y *= br->mtex.size[1]; + + x += br->mtex.ofs[0]; + y += br->mtex.ofs[1]; + + avg = br->mtex.tex ? paint_get_tex_pixel(br, x, y) : 1; + + avg += br->texture_sample_bias; + + if (br->mtex.brush_map_mode == MTEX_MAP_MODE_FIXED) + avg *= brush_curve_strength(br, len, 1); /* Falloff curve */ + + buffer[index] = 255 - (GLubyte)(255*avg); + } + else { + buffer[index] = 0; + } + } + } + + if (!overlay_texture) + glGenTextures(1, &overlay_texture); + } + else { + size= old_size; + } + + glBindTexture(GL_TEXTURE_2D, overlay_texture); + + if (refresh) { + if (!init) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, size, size, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buffer); + init = 1; + } + else { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, GL_ALPHA, GL_UNSIGNED_BYTE, buffer); + } + + if (buffer) + MEM_freeN(buffer); + } + + glEnable(GL_TEXTURE_2D); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + if (br->mtex.brush_map_mode == MTEX_MAP_MODE_FIXED) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + } + + return 1; +} + +static int project_brush_radius(ViewContext *vc, + float radius, + const float location[3]) +{ + float view[3], nonortho[3], ortho[3], offset[3], p1[2], p2[2]; + + ED_view3d_global_to_vector(vc->rv3d, location, view); + + // create a vector that is not orthogonal to view + + if (fabsf(view[0]) < 0.1f) { + nonortho[0] = view[0] + 1.0f; + nonortho[1] = view[1]; + nonortho[2] = view[2]; + } + else if (fabsf(view[1]) < 0.1f) { + nonortho[0] = view[0]; + nonortho[1] = view[1] + 1.0f; + nonortho[2] = view[2]; + } + else { + nonortho[0] = view[0]; + nonortho[1] = view[1]; + nonortho[2] = view[2] + 1.0f; + } + + // get a vector in the plane of the view + cross_v3_v3v3(ortho, nonortho, view); + normalize_v3(ortho); + + // make a point on the surface of the brush tagent to the view + mul_v3_fl(ortho, radius); + add_v3_v3v3(offset, location, ortho); + + // project the center of the brush, and the tangent point to the view onto the screen + project_float(vc->ar, location, p1); + project_float(vc->ar, offset, p2); + + // the distance between these points is the size of the projected brush in pixels + return len_v2v2(p1, p2); +} + +static int sculpt_get_brush_geometry(bContext* C, ViewContext *vc, + int x, int y, int* pixel_radius, + float location[3]) +{ + Scene *scene = CTX_data_scene(C); + Paint *paint = paint_get_active(scene); + Brush *brush = paint_brush(paint); + float window[2]; + int hit; + + window[0] = x + vc->ar->winrct.xmin; + window[1] = y + vc->ar->winrct.ymin; + + if(vc->obact->sculpt && vc->obact->sculpt->pbvh && + sculpt_stroke_get_location(C, location, window)) { + *pixel_radius = + project_brush_radius(vc, + brush_unprojected_radius(scene, brush), + location); + + if (*pixel_radius == 0) + *pixel_radius = brush_size(scene, brush); + + mul_m4_v3(vc->obact->obmat, location); + + hit = 1; + } + else { + Sculpt* sd = CTX_data_tool_settings(C)->sculpt; + Brush* brush = paint_brush(&sd->paint); + + *pixel_radius = brush_size(scene, brush); + hit = 0; + } + + return hit; +} + +/* Draw an overlay that shows what effect the brush's texture will + have on brush strength */ +/* TODO: sculpt only for now */ +static void paint_draw_alpha_overlay(Sculpt *sd, Brush *brush, + ViewContext *vc, int x, int y) +{ + rctf quad; + + /* check for overlay mode */ + if(!(brush->flag & BRUSH_TEXTURE_OVERLAY) || + !(ELEM(brush->mtex.brush_map_mode, MTEX_MAP_MODE_FIXED, MTEX_MAP_MODE_TILED))) + return; + + /* save lots of GL state + TODO: check on whether all of these are needed? */ + glPushAttrib(GL_COLOR_BUFFER_BIT| + GL_CURRENT_BIT| + GL_DEPTH_BUFFER_BIT| + GL_ENABLE_BIT| + GL_LINE_BIT| + GL_POLYGON_BIT| + GL_STENCIL_BUFFER_BIT| + GL_TRANSFORM_BIT| + GL_VIEWPORT_BIT| + GL_TEXTURE_BIT); + + if(load_tex(sd, brush, vc)) { + glEnable(GL_BLEND); + + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDepthMask(GL_FALSE); + glDepthFunc(GL_ALWAYS); + + glMatrixMode(GL_TEXTURE); + glPushMatrix(); + glLoadIdentity(); + + if(brush->mtex.brush_map_mode == MTEX_MAP_MODE_FIXED) { + /* brush rotation */ + glTranslatef(0.5, 0.5, 0); + glRotatef((double)RAD2DEGF((brush->flag & BRUSH_RAKE) ? + sd->last_angle : sd->special_rotation), + 0.0, 0.0, 1.0); + glTranslatef(-0.5f, -0.5f, 0); + + /* scale based on tablet pressure */ + if(sd->draw_pressure && brush_use_size_pressure(vc->scene, brush)) { + glTranslatef(0.5f, 0.5f, 0); + glScalef(1.0f/sd->pressure_value, 1.0f/sd->pressure_value, 1); + glTranslatef(-0.5f, -0.5f, 0); + } + + if(sd->draw_anchored) { + const float *aim = sd->anchored_initial_mouse; + const rcti *win = &vc->ar->winrct; + quad.xmin = aim[0]-sd->anchored_size - win->xmin; + quad.ymin = aim[1]-sd->anchored_size - win->ymin; + quad.xmax = aim[0]+sd->anchored_size - win->xmin; + quad.ymax = aim[1]+sd->anchored_size - win->ymin; + } + else { + const int radius= brush_size(vc->scene, brush); + quad.xmin = x - radius; + quad.ymin = y - radius; + quad.xmax = x + radius; + quad.ymax = y + radius; + } + } + else { + quad.xmin = 0; + quad.ymin = 0; + quad.xmax = vc->ar->winrct.xmax - vc->ar->winrct.xmin; + quad.ymax = vc->ar->winrct.ymax - vc->ar->winrct.ymin; + } + + /* set quad color */ + glColor4f(U.sculpt_paint_overlay_col[0], + U.sculpt_paint_overlay_col[1], + U.sculpt_paint_overlay_col[2], + brush->texture_overlay_alpha / 100.0f); + + /* draw textured quad */ + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(quad.xmin, quad.ymin); + glTexCoord2f(1, 0); + glVertex2f(quad.xmax, quad.ymin); + glTexCoord2f(1, 1); + glVertex2f(quad.xmax, quad.ymax); + glTexCoord2f(0, 1); + glVertex2f(quad.xmin, quad.ymax); + glEnd(); + + glPopMatrix(); + } + + glPopAttrib(); +} + +/* Special actions taken when paint cursor goes over mesh */ +/* TODO: sculpt only for now */ +static void paint_cursor_on_hit(Sculpt *sd, Brush *brush, ViewContext *vc, + const float location[3]) +{ + float unprojected_radius, projected_radius; + + /* update the brush's cached 3D radius */ + if(!brush_use_locked_size(vc->scene, brush)) { + /* get 2D brush radius */ + if(sd->draw_anchored) + projected_radius = sd->anchored_size; + else { + if(brush->flag & BRUSH_ANCHORED) + projected_radius = 8; + else + projected_radius = brush_size(vc->scene, brush); + } + + /* convert brush radius from 2D to 3D */ + unprojected_radius = paint_calc_object_space_radius(vc, location, + projected_radius); + + /* scale 3D brush radius by pressure */ + if(sd->draw_pressure && brush_use_size_pressure(vc->scene, brush)) + unprojected_radius *= sd->pressure_value; + + /* set cached value in either Brush or UnifiedPaintSettings */ + brush_set_unprojected_radius(vc->scene, brush, unprojected_radius); + } +} + +static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) +{ + Scene *scene = CTX_data_scene(C); + Paint *paint = paint_get_active(scene); + Brush *brush = paint_brush(paint); + ViewContext vc; + float final_radius; + float translation[2]; + float outline_alpha, *outline_col; + + /* set various defaults */ + translation[0] = x; + translation[1] = y; + outline_alpha = 0.5; + outline_col = brush->add_col; + final_radius = brush_size(scene, brush); + + /* check that brush drawing is enabled */ + if(!(paint->flags & PAINT_SHOW_BRUSH)) + return; + + /* can't use stroke vc here because this will be called during + mouse over too, not just during a stroke */ + view3d_set_viewcontext(C, &vc); + + /* TODO: as sculpt and other paint modes are unified, this + special mode of drawing will go away */ + if(vc.obact->sculpt) { + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + float location[3]; + int pixel_radius, hit; + + /* this is probably here so that rake takes into + account the brush movements before the stroke + starts, but this doesn't really belong in draw code + (TODO) */ + { + const float u = 0.5f; + const float v = 1 - u; + const float r = 20; + + const float dx = sd->last_x - x; + const float dy = sd->last_y - y; + + if(dx*dx + dy*dy >= r*r) { + sd->last_angle = atan2(dx, dy); + + sd->last_x = u*sd->last_x + v*x; + sd->last_y = u*sd->last_y + v*y; + } + } + + /* test if brush is over the mesh */ + hit = sculpt_get_brush_geometry(C, &vc, x, y, &pixel_radius, location); + + /* draw overlay */ + paint_draw_alpha_overlay(sd, brush, &vc, x, y); + + if(brush_use_locked_size(scene, brush)) + brush_set_size(scene, brush, pixel_radius); + + /* check if brush is subtracting, use different color then */ + /* TODO: no way currently to know state of pen flip or + invert key modifier without starting a stroke */ + if((!(brush->flag & BRUSH_INVERTED) ^ + !(brush->flag & BRUSH_DIR_IN)) && + ELEM5(brush->sculpt_tool, SCULPT_TOOL_DRAW, + SCULPT_TOOL_INFLATE, SCULPT_TOOL_CLAY, + SCULPT_TOOL_PINCH, SCULPT_TOOL_CREASE)) + outline_col = brush->sub_col; + + /* only do if brush is over the mesh */ + if(hit) + paint_cursor_on_hit(sd, brush, &vc, location); + + if(sd->draw_anchored) { + final_radius = sd->anchored_size; + translation[0] = sd->anchored_initial_mouse[0] - vc.ar->winrct.xmin; + translation[1] = sd->anchored_initial_mouse[1] - vc.ar->winrct.ymin; + } + } + + /* make lines pretty */ + glEnable(GL_BLEND); + glEnable(GL_LINE_SMOOTH); + + /* set brush color */ + glColor4f(outline_col[0], outline_col[1], outline_col[2], outline_alpha); + + /* draw brush outline */ + glTranslatef(translation[0], translation[1], 0); + glutil_draw_lined_arc(0.0, M_PI*2.0, final_radius, 40); + glTranslatef(-translation[0], -translation[1], 0); + + /* restore GL state */ + glDisable(GL_BLEND); + glDisable(GL_LINE_SMOOTH); +} + +/* Public API */ + +void paint_cursor_start(bContext *C, int (*poll)(bContext *C)) +{ + Paint *p = paint_get_active(CTX_data_scene(C)); + + if(p && !p->paint_cursor) + p->paint_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), poll, paint_draw_cursor, NULL); +} diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 4ca05e1fbd7..73dc1e236f6 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -50,7 +50,7 @@ struct wmOperator; struct wmOperatorType; /* paint_stroke.c */ -typedef int (*StrokeGetLocation)(struct bContext *C, struct PaintStroke *stroke, float location[3], float mouse[2]); +typedef int (*StrokeGetLocation)(struct bContext *C, float location[3], float mouse[2]); typedef int (*StrokeTestStart)(struct bContext *C, struct wmOperator *op, struct wmEvent *event); typedef void (*StrokeUpdateStep)(struct bContext *C, struct PaintStroke *stroke, struct PointerRNA *itemptr); typedef void (*StrokeDone)(struct bContext *C, struct PaintStroke *stroke); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 67bd6ca9255..cd8262f06bd 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -56,9 +56,6 @@ #include "ED_view3d.h" #include "paint_intern.h" -/* still needed for sculpt_stroke_get_location, should be - removed eventually (TODO) */ -#include "sculpt_intern.h" #include <float.h> #include <math.h> @@ -108,552 +105,6 @@ static void paint_draw_smooth_stroke(bContext *C, int x, int y, void *customdata glDisable(GL_LINE_SMOOTH); } -typedef struct Snapshot { - float size[3]; - float ofs[3]; - float rot; - int brush_size; - int winx; - int winy; - int brush_map_mode; - int curve_changed_timestamp; -} Snapshot; - -static int same_snap(Snapshot* snap, Brush* brush, ViewContext* vc) -{ - MTex* mtex = &brush->mtex; - - return (((mtex->tex) && - equals_v3v3(mtex->ofs, snap->ofs) && - equals_v3v3(mtex->size, snap->size) && - mtex->rot == snap->rot) && - - /* make brush smaller shouldn't cause a resample */ - ((mtex->brush_map_mode == MTEX_MAP_MODE_FIXED && - (brush_size(vc->scene, brush) <= snap->brush_size)) || - (brush_size(vc->scene, brush) == snap->brush_size)) && - - (mtex->brush_map_mode == snap->brush_map_mode) && - (vc->ar->winx == snap->winx) && - (vc->ar->winy == snap->winy)); -} - -static void make_snap(Snapshot* snap, Brush* brush, ViewContext* vc) -{ - if (brush->mtex.tex) { - snap->brush_map_mode = brush->mtex.brush_map_mode; - copy_v3_v3(snap->ofs, brush->mtex.ofs); - copy_v3_v3(snap->size, brush->mtex.size); - snap->rot = brush->mtex.rot; - } - else { - snap->brush_map_mode = -1; - snap->ofs[0]= snap->ofs[1]= snap->ofs[2]= -1; - snap->size[0]= snap->size[1]= snap->size[2]= -1; - snap->rot = -1; - } - - snap->brush_size = brush_size(vc->scene, brush); - snap->winx = vc->ar->winx; - snap->winy = vc->ar->winy; -} - -static int load_tex(Sculpt *sd, Brush* br, ViewContext* vc) -{ - static GLuint overlay_texture = 0; - static int init = 0; - static int tex_changed_timestamp = -1; - static int curve_changed_timestamp = -1; - static Snapshot snap; - static int old_size = -1; - - GLubyte* buffer = NULL; - - int size; - int j; - int refresh; - -#ifndef _OPENMP - (void)sd; /* quied unused warning */ -#endif - - if (br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED && !br->mtex.tex) return 0; - - refresh = - !overlay_texture || - (br->mtex.tex && - (!br->mtex.tex->preview || - br->mtex.tex->preview->changed_timestamp[0] != tex_changed_timestamp)) || - !br->curve || - br->curve->changed_timestamp != curve_changed_timestamp || - !same_snap(&snap, br, vc); - - if (refresh) { - if (br->mtex.tex && br->mtex.tex->preview) - tex_changed_timestamp = br->mtex.tex->preview->changed_timestamp[0]; - - if (br->curve) - curve_changed_timestamp = br->curve->changed_timestamp; - - make_snap(&snap, br, vc); - - if (br->mtex.brush_map_mode == MTEX_MAP_MODE_FIXED) { - int s = brush_size(vc->scene, br); - int r = 1; - - for (s >>= 1; s > 0; s >>= 1) - r++; - - size = (1<<r); - - if (size < 256) - size = 256; - - if (size < old_size) - size = old_size; - } - else - size = 512; - - if (old_size != size) { - if (overlay_texture) { - glDeleteTextures(1, &overlay_texture); - overlay_texture = 0; - } - - init = 0; - - old_size = size; - } - - buffer = MEM_mallocN(sizeof(GLubyte)*size*size, "load_tex"); - - #pragma omp parallel for schedule(static) if (sd->flags & SCULPT_USE_OPENMP) - for (j= 0; j < size; j++) { - int i; - float y; - float len; - - for (i= 0; i < size; i++) { - - // largely duplicated from tex_strength - - const float rotation = -br->mtex.rot; - float radius = brush_size(vc->scene, br); - int index = j*size + i; - float x; - float avg; - - x = (float)i/size; - y = (float)j/size; - - x -= 0.5f; - y -= 0.5f; - - if (br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED) { - x *= vc->ar->winx / radius; - y *= vc->ar->winy / radius; - } - else { - x *= 2; - y *= 2; - } - - len = sqrtf(x*x + y*y); - - if ((br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED) || len <= 1) { - /* it is probably worth optimizing for those cases where - the texture is not rotated by skipping the calls to - atan2, sqrtf, sin, and cos. */ - if (br->mtex.tex && (rotation > 0.001f || rotation < -0.001f)) { - const float angle = atan2f(y, x) + rotation; - - x = len * cosf(angle); - y = len * sinf(angle); - } - - x *= br->mtex.size[0]; - y *= br->mtex.size[1]; - - x += br->mtex.ofs[0]; - y += br->mtex.ofs[1]; - - avg = br->mtex.tex ? paint_get_tex_pixel(br, x, y) : 1; - - avg += br->texture_sample_bias; - - if (br->mtex.brush_map_mode == MTEX_MAP_MODE_FIXED) - avg *= brush_curve_strength(br, len, 1); /* Falloff curve */ - - buffer[index] = 255 - (GLubyte)(255*avg); - } - else { - buffer[index] = 0; - } - } - } - - if (!overlay_texture) - glGenTextures(1, &overlay_texture); - } - else { - size= old_size; - } - - glBindTexture(GL_TEXTURE_2D, overlay_texture); - - if (refresh) { - if (!init) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, size, size, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buffer); - init = 1; - } - else { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, GL_ALPHA, GL_UNSIGNED_BYTE, buffer); - } - - if (buffer) - MEM_freeN(buffer); - } - - glEnable(GL_TEXTURE_2D); - - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - if (br->mtex.brush_map_mode == MTEX_MAP_MODE_FIXED) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - } - - return 1; -} - -static int project_brush_radius(RegionView3D* rv3d, float radius, float location[3], bglMats* mats) -{ - float view[3], nonortho[3], ortho[3], offset[3], p1[2], p2[2]; - - ED_view3d_global_to_vector(rv3d, location, view); - - // create a vector that is not orthogonal to view - - if (fabsf(view[0]) < 0.1f) { - nonortho[0] = view[0] + 1.0f; - nonortho[1] = view[1]; - nonortho[2] = view[2]; - } - else if (fabsf(view[1]) < 0.1f) { - nonortho[0] = view[0]; - nonortho[1] = view[1] + 1.0f; - nonortho[2] = view[2]; - } - else { - nonortho[0] = view[0]; - nonortho[1] = view[1]; - nonortho[2] = view[2] + 1.0f; - } - - // get a vector in the plane of the view - cross_v3_v3v3(ortho, nonortho, view); - normalize_v3(ortho); - - // make a point on the surface of the brush tagent to the view - mul_v3_fl(ortho, radius); - add_v3_v3v3(offset, location, ortho); - - // project the center of the brush, and the tagent point to the view onto the screen - projectf(mats, location, p1); - projectf(mats, offset, p2); - - // the distance between these points is the size of the projected brush in pixels - return len_v2v2(p1, p2); -} - -static int sculpt_get_brush_geometry(bContext* C, int x, int y, int* pixel_radius, - float location[3]) -{ - struct PaintStroke *stroke; - const Scene *scene = CTX_data_scene(C); - float window[2]; - int hit; - - stroke = paint_stroke_new(C, NULL, NULL, NULL, NULL, 0); - - window[0] = x + stroke->vc.ar->winrct.xmin; - window[1] = y + stroke->vc.ar->winrct.ymin; - - if(stroke->vc.obact->sculpt && stroke->vc.obact->sculpt->pbvh && - sculpt_stroke_get_location(C, stroke, location, window)) { - *pixel_radius = project_brush_radius(stroke->vc.rv3d, - brush_unprojected_radius(scene, stroke->brush), - location, &stroke->mats); - - if (*pixel_radius == 0) - *pixel_radius = brush_size(scene, stroke->brush); - - mul_m4_v3(stroke->vc.obact->obmat, location); - - hit = 1; - } - else { - Sculpt* sd = CTX_data_tool_settings(C)->sculpt; - Brush* brush = paint_brush(&sd->paint); - - *pixel_radius = brush_size(scene, brush); - hit = 0; - } - - paint_stroke_free(stroke); - - return hit; -} - -/* Draw an overlay that shows what effect the brush's texture will - have on brush strength */ -/* TODO: sculpt only for now */ -static void paint_draw_alpha_overlay(Sculpt *sd, Brush *brush, - ViewContext *vc, int x, int y) -{ - rctf quad; - - /* check for overlay mode */ - if(!(brush->flag & BRUSH_TEXTURE_OVERLAY) || - !(ELEM(brush->mtex.brush_map_mode, MTEX_MAP_MODE_FIXED, MTEX_MAP_MODE_TILED))) - return; - - /* save lots of GL state - TODO: check on whether all of these are needed? */ - glPushAttrib(GL_COLOR_BUFFER_BIT| - GL_CURRENT_BIT| - GL_DEPTH_BUFFER_BIT| - GL_ENABLE_BIT| - GL_LINE_BIT| - GL_POLYGON_BIT| - GL_STENCIL_BUFFER_BIT| - GL_TRANSFORM_BIT| - GL_VIEWPORT_BIT| - GL_TEXTURE_BIT); - - if(load_tex(sd, brush, vc)) { - glEnable(GL_BLEND); - - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDepthMask(GL_FALSE); - glDepthFunc(GL_ALWAYS); - - glMatrixMode(GL_TEXTURE); - glPushMatrix(); - glLoadIdentity(); - - if(brush->mtex.brush_map_mode == MTEX_MAP_MODE_FIXED) { - /* brush rotation */ - glTranslatef(0.5, 0.5, 0); - glRotatef((double)RAD2DEGF((brush->flag & BRUSH_RAKE) ? - sd->last_angle : sd->special_rotation), - 0.0, 0.0, 1.0); - glTranslatef(-0.5f, -0.5f, 0); - - /* scale based on tablet pressure */ - if(sd->draw_pressure && brush_use_size_pressure(vc->scene, brush)) { - glTranslatef(0.5f, 0.5f, 0); - glScalef(1.0f/sd->pressure_value, 1.0f/sd->pressure_value, 1); - glTranslatef(-0.5f, -0.5f, 0); - } - - if(sd->draw_anchored) { - const float *aim = sd->anchored_initial_mouse; - const rcti *win = &vc->ar->winrct; - quad.xmin = aim[0]-sd->anchored_size - win->xmin; - quad.ymin = aim[1]-sd->anchored_size - win->ymin; - quad.xmax = aim[0]+sd->anchored_size - win->xmin; - quad.ymax = aim[1]+sd->anchored_size - win->ymin; - } - else { - const int radius= brush_size(vc->scene, brush); - quad.xmin = x - radius; - quad.ymin = y - radius; - quad.xmax = x + radius; - quad.ymax = y + radius; - } - } - else { - quad.xmin = 0; - quad.ymin = 0; - quad.xmax = vc->ar->winrct.xmax - vc->ar->winrct.xmin; - quad.ymax = vc->ar->winrct.ymax - vc->ar->winrct.ymin; - } - - /* set quad color */ - glColor4f(U.sculpt_paint_overlay_col[0], - U.sculpt_paint_overlay_col[1], - U.sculpt_paint_overlay_col[2], - brush->texture_overlay_alpha / 100.0f); - - /* draw textured quad */ - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2f(quad.xmin, quad.ymin); - glTexCoord2f(1, 0); - glVertex2f(quad.xmax, quad.ymin); - glTexCoord2f(1, 1); - glVertex2f(quad.xmax, quad.ymax); - glTexCoord2f(0, 1); - glVertex2f(quad.xmin, quad.ymax); - glEnd(); - - glPopMatrix(); - } - - glPopAttrib(); -} - -/* Special actions taken when paint cursor goes over mesh */ -/* TODO: sculpt only for now */ -static void paint_cursor_on_hit(Sculpt *sd, Brush *brush, ViewContext *vc, - const float location[3]) -{ - float unprojected_radius, projected_radius; - - /* update the brush's cached 3D radius */ - if(!brush_use_locked_size(vc->scene, brush)) { - /* get 2D brush radius */ - if(sd->draw_anchored) - projected_radius = sd->anchored_size; - else { - if(brush->flag & BRUSH_ANCHORED) - projected_radius = 8; - else - projected_radius = brush_size(vc->scene, brush); - } - - /* convert brush radius from 2D to 3D */ - unprojected_radius = paint_calc_object_space_radius(vc, location, - projected_radius); - - /* scale 3D brush radius by pressure */ - if(sd->draw_pressure && brush_use_size_pressure(vc->scene, brush)) - unprojected_radius *= sd->pressure_value; - - /* set cached value in either Brush or UnifiedPaintSettings */ - brush_set_unprojected_radius(vc->scene, brush, unprojected_radius); - } -} - -static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) -{ - Scene *scene = CTX_data_scene(C); - Paint *paint = paint_get_active(scene); - Brush *brush = paint_brush(paint); - ViewContext vc; - float final_radius; - float translation[2]; - float outline_alpha, *outline_col; - - /* set various defaults */ - translation[0] = x; - translation[1] = y; - outline_alpha = 0.5; - outline_col = brush->add_col; - final_radius = brush_size(scene, brush); - - /* check that brush drawing is enabled */ - if(!(paint->flags & PAINT_SHOW_BRUSH)) - return; - - /* can't use stroke vc here because this will be called during - mouse over too, not just during a stroke */ - view3d_set_viewcontext(C, &vc); - - /* TODO: as sculpt and other paint modes are unified, this - special mode of drawing will go away */ - if(vc.obact->sculpt) { - Sculpt *sd = CTX_data_tool_settings(C)->sculpt; - float location[3]; - int pixel_radius, hit; - const float root_alpha = brush_alpha(scene, brush); - float visual_strength = root_alpha*root_alpha; - const float min_alpha = 0.20f; - const float max_alpha = 0.80f; - - /* this is probably here so that rake takes into - account the brush movements before the stroke - starts, but this doesn't really belong in draw code - (TODO) */ - { - const float u = 0.5f; - const float v = 1 - u; - const float r = 20; - - const float dx = sd->last_x - x; - const float dy = sd->last_y - y; - - if(dx*dx + dy*dy >= r*r) { - sd->last_angle = atan2(dx, dy); - - sd->last_x = u*sd->last_x + v*x; - sd->last_y = u*sd->last_y + v*y; - } - } - - /* test if brush is over the mesh */ - hit = sculpt_get_brush_geometry(C, x, y, &pixel_radius, location); - - /* draw overlay */ - paint_draw_alpha_overlay(sd, brush, &vc, x, y); - - if(brush_use_locked_size(scene, brush)) - brush_set_size(scene, brush, pixel_radius); - - /* check if brush is subtracting, use different color then */ - /* TODO: no way currently to know state of pen flip or - invert key modifier without starting a stroke */ - if((!(brush->flag & BRUSH_INVERTED) ^ - !(brush->flag & BRUSH_DIR_IN)) && - ELEM5(brush->sculpt_tool, SCULPT_TOOL_DRAW, - SCULPT_TOOL_INFLATE, SCULPT_TOOL_CLAY, - SCULPT_TOOL_PINCH, SCULPT_TOOL_CREASE)) - outline_col = brush->sub_col; - - /* only do if brush is over the mesh */ - if(hit) { - /* scale the alpha by pen pressure */ - if(sd->draw_pressure && brush_use_alpha_pressure(vc.scene, brush)) - visual_strength *= sd->pressure_value; - - paint_cursor_on_hit(sd, brush, &vc, location); - } - - /* don't show effect of strength past the soft limit */ - if(visual_strength > 1) - visual_strength = 1; - - outline_alpha = ((paint->flags & PAINT_SHOW_BRUSH_ON_SURFACE) ? - min_alpha + (visual_strength*(max_alpha-min_alpha)) : 0.50f); - - if(sd->draw_anchored) { - final_radius = sd->anchored_size; - translation[0] = sd->anchored_initial_mouse[0] - vc.ar->winrct.xmin; - translation[1] = sd->anchored_initial_mouse[1] - vc.ar->winrct.ymin; - } - } - - /* make lines pretty */ - glEnable(GL_BLEND); - glEnable(GL_LINE_SMOOTH); - - /* set brush color */ - glColor4f(outline_col[0], outline_col[1], outline_col[2], outline_alpha); - - /* draw brush outline */ - glTranslatef(translation[0], translation[1], 0); - glutil_draw_lined_arc(0.0, M_PI*2.0, final_radius, 40); - glTranslatef(-translation[0], -translation[1], 0); - - /* restore GL state */ - glDisable(GL_BLEND); - glDisable(GL_LINE_SMOOTH); -} - /* if this is a tablet event, return tablet pressure and set *pen_flip to 1 if the eraser tool is being used, 0 otherwise */ static float event_tablet_data(wmEvent *event, int *pen_flip) @@ -712,7 +163,7 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *ev /* TODO: can remove the if statement once all modes have this */ if(stroke->get_location) - stroke->get_location(C, stroke, location, mouse); + stroke->get_location(C, location, mouse); else zero_v3(location); @@ -976,12 +427,3 @@ int paint_poll(bContext *C) CTX_wm_area(C)->spacetype == SPACE_VIEW3D && CTX_wm_region(C)->regiontype == RGN_TYPE_WINDOW; } - -void paint_cursor_start(bContext *C, int (*poll)(bContext *C)) -{ - Paint *p = paint_get_active(CTX_data_scene(C)); - - if(p && !p->paint_cursor) - p->paint_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), poll, paint_draw_cursor, NULL); -} - diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index ae5316e71c4..308534ab35c 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -3105,7 +3105,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, halfway[0] = (float)dx * 0.5f + cache->initial_mouse[0]; halfway[1] = (float)dy * 0.5f + cache->initial_mouse[1]; - if (sculpt_stroke_get_location(C, stroke, out, halfway)) { + if (sculpt_stroke_get_location(C, out, halfway)) { copy_v3_v3(sd->anchored_location, out); copy_v2_v2(sd->anchored_initial_mouse, halfway); copy_v2_v2(cache->tex_mouse, halfway); @@ -3207,23 +3207,29 @@ static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float* tmin) (This allows us to ignore the GL depth buffer) Returns 0 if the ray doesn't hit the mesh, non-zero otherwise */ -int sculpt_stroke_get_location(bContext *C, struct PaintStroke *stroke, float out[3], float mouse[2]) +int sculpt_stroke_get_location(bContext *C, float out[3], float mouse[2]) { - ViewContext *vc = paint_stroke_view_context(stroke); - Object *ob = vc->obact; - SculptSession *ss= ob->sculpt; - StrokeCache *cache= ss->cache; + ViewContext vc; + Object *ob; + SculptSession *ss; + StrokeCache *cache; float ray_start[3], ray_end[3], ray_normal[3], dist; float obimat[4][4]; float mval[2]; SculptRaycastData srd; - mval[0] = mouse[0] - vc->ar->winrct.xmin; - mval[1] = mouse[1] - vc->ar->winrct.ymin; + view3d_set_viewcontext(C, &vc); + + ob = vc.obact; + ss = ob->sculpt; + cache = ss->cache; sculpt_stroke_modifiers_check(C, ob); - ED_view3d_win_to_segment_clip(vc->ar, vc->v3d, mval, ray_start, ray_end); + mval[0] = mouse[0] - vc.ar->winrct.xmin; + mval[1] = mouse[1] - vc.ar->winrct.ymin; + + ED_view3d_win_to_segment_clip(vc.ar, vc.v3d, mval, ray_start, ray_end); invert_m4_m4(obimat, ob->obmat); mul_m4_v3(obimat, ray_start); @@ -3232,7 +3238,7 @@ int sculpt_stroke_get_location(bContext *C, struct PaintStroke *stroke, float ou sub_v3_v3v3(ray_normal, ray_end, ray_start); dist= normalize_v3(ray_normal); - srd.ss = vc->obact->sculpt; + srd.ss = vc.obact->sculpt; srd.ray_start = ray_start; srd.ray_normal = ray_normal; srd.dist = dist; @@ -3371,14 +3377,14 @@ static void sculpt_flush_update(bContext *C) /* Returns whether the mouse/stylus is over the mesh (1) or over the background (0) */ -static int over_mesh(bContext *C, struct wmOperator *op, float x, float y) +static int over_mesh(bContext *C, struct wmOperator *UNUSED(op), float x, float y) { float mouse[2], co[3]; mouse[0] = x; mouse[1] = y; - return sculpt_stroke_get_location(C, op->customdata, co, mouse); + return sculpt_stroke_get_location(C, co, mouse); } static int sculpt_stroke_test_start(bContext *C, struct wmOperator *op, diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 42205a8da04..275d1d52355 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -73,7 +73,7 @@ void sculpt_stroke_free(struct SculptStroke *); void sculpt_stroke_add_point(struct SculptStroke *, const short x, const short y); void sculpt_stroke_apply(struct Sculpt *sd, struct SculptStroke *); void sculpt_stroke_apply_all(struct Sculpt *sd, struct SculptStroke *); -int sculpt_stroke_get_location(bContext *C, struct PaintStroke *stroke, float out[3], float mouse[2]); +int sculpt_stroke_get_location(bContext *C, float out[3], float mouse[2]); /* Undo */ diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c index 9aba6db0c80..e913ae77f05 100644 --- a/source/blender/editors/space_clip/clip_graph_draw.c +++ b/source/blender/editors/space_clip/clip_graph_draw.c @@ -155,15 +155,16 @@ void tracking_segment_end_cb(void *UNUSED(userdata)) } static void tracking_segment_knot_cb(void *userdata, MovieTrackingTrack *track, - MovieTrackingMarker *marker, int UNUSED(coord), float val) + MovieTrackingMarker *marker, int coord, float val) { struct { MovieTrackingTrack *act_track; int sel; float xscale, yscale, hsize; } *data = userdata; - int sel= 0; + int sel= 0, sel_flag; if(track!=data->act_track) return; - sel= (marker->flag&MARKER_GRAPH_SEL) ? 1 : 0; + sel_flag= coord == 0 ? MARKER_GRAPH_SEL_X : MARKER_GRAPH_SEL_Y; + sel= (marker->flag & sel_flag) ? 1 : 0; if(sel == data->sel) { if(sel) UI_ThemeColor(TH_HANDLE_VERTEX_SELECT); diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c index 08d6bcf47bc..8be5e520b1f 100644 --- a/source/blender/editors/space_clip/clip_graph_ops.c +++ b/source/blender/editors/space_clip/clip_graph_ops.c @@ -68,13 +68,13 @@ static void toggle_selection_cb(void *userdata, MovieTrackingMarker *marker) switch(data->action) { case SEL_SELECT: - marker->flag|= MARKER_GRAPH_SEL; + marker->flag|= (MARKER_GRAPH_SEL_X|MARKER_GRAPH_SEL_Y); break; case SEL_DESELECT: - marker->flag&= ~MARKER_GRAPH_SEL; + marker->flag&= ~(MARKER_GRAPH_SEL_X|MARKER_GRAPH_SEL_Y); break; case SEL_INVERT: - marker->flag^= MARKER_GRAPH_SEL; + marker->flag^= (MARKER_GRAPH_SEL_X|MARKER_GRAPH_SEL_Y); break; } } @@ -177,7 +177,10 @@ static int mouse_select_knot(bContext *C, float co[2], int extend) clip_graph_tracking_iterate(sc, &selectdata, toggle_selection_cb); } - userdata.marker->flag|= MARKER_GRAPH_SEL; + if(userdata.coord==0) + userdata.marker->flag|= MARKER_GRAPH_SEL_X; + else + userdata.marker->flag|= MARKER_GRAPH_SEL_Y; return 1; } @@ -335,7 +338,7 @@ static int delete_knot_exec(bContext *C, wmOperator *UNUSED(op)) while(a<act_track->markersnr) { MovieTrackingMarker *marker= &act_track->markers[a]; - if(marker->flag&MARKER_GRAPH_SEL) + if(marker->flag & (MARKER_GRAPH_SEL_X|MARKER_GRAPH_SEL_Y)) clip_delete_marker(C, clip, tracksbase, act_track, marker); else a++; diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index 3ca8fc35c7f..46442d39a7b 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -95,7 +95,7 @@ void clip_graph_tracking_values_iterate_track(SpaceClip *sc, MovieTrackingTrack } /* value is a pixels per frame speed */ - val= (marker->pos[coord] - prevval) * ((i==0) ? (width) : (height)); + val= (marker->pos[coord] - prevval) * ((coord==0) ? (width) : (height)); val/= marker->framenr-prevfra; if(func) diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 3d584378135..04871156412 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -545,6 +545,8 @@ static void clip_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "CLIP_OT_graph_delete_knot", DELKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "CLIP_OT_graph_delete_knot", XKEY, KM_PRESS, KM_SHIFT, 0); + + transform_keymap_for_space(keyconf, keymap, SPACE_CLIP); } const char *clip_context_dir[]= {"edit_movieclip", NULL}; diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index b67fac69745..6cf8a988571 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -2520,9 +2520,8 @@ static int set_scale_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); - float dist= RNA_float_get(op->ptr, "distance"); - if(dist==0.0f) + if(!RNA_struct_property_is_set(op->ptr, "distance")) RNA_float_set(op->ptr, "distance", clip->tracking.settings.dist); return set_scale_exec(C, op); @@ -2573,9 +2572,8 @@ static int set_solution_scale_invoke(bContext *C, wmOperator *op, wmEvent *UNUSE { SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); - float dist= RNA_float_get(op->ptr, "distance"); - if(dist==0.0f) + if(!RNA_struct_property_is_set(op->ptr, "distance")) RNA_float_set(op->ptr, "distance", clip->tracking.settings.object_distance); return set_solution_scale_exec(C, op); diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 4065b3e2e0b..3b6b4334880 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -198,6 +198,8 @@ void OUTLINER_OT_show_one_level(struct wmOperatorType *ot); void OUTLINER_OT_show_active(struct wmOperatorType *ot); void OUTLINER_OT_show_hierarchy(struct wmOperatorType *ot); +void OUTLINER_OT_select_border(struct wmOperatorType *ot); + void OUTLINER_OT_selected_toggle(struct wmOperatorType *ot); void OUTLINER_OT_expanded_toggle(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index a424520c76f..631bbcd7d0f 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -49,6 +49,7 @@ void outliner_operatortypes(void) { WM_operatortype_append(OUTLINER_OT_item_activate); + WM_operatortype_append(OUTLINER_OT_select_border); WM_operatortype_append(OUTLINER_OT_item_openclose); WM_operatortype_append(OUTLINER_OT_item_rename); WM_operatortype_append(OUTLINER_OT_operation); @@ -89,6 +90,9 @@ void outliner_keymap(wmKeyConfig *keyconf) RNA_boolean_set(kmi->ptr, "extend", FALSE); kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "extend", TRUE); + + WM_keymap_add_item(keymap, "OUTLINER_OT_select_border", BKEY, KM_PRESS, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "OUTLINER_OT_select_border", EVT_TWEAK_L, KM_ANY, 0, 0)->ptr, "tweak", 1); kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_openclose", RETKEY, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "all", FALSE); diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index bf570c929cc..345e7a835f4 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -875,3 +875,78 @@ void OUTLINER_OT_item_activate(wmOperatorType *ot) } /* ****************************************************** */ + +/* **************** Border Select Tool ****************** */ +static void outliner_item_border_select(Scene *scene, SpaceOops *soops, rctf *rectf, TreeElement *te, int gesture_mode) +{ + TreeStoreElem *tselem= TREESTORE(te); + + if (te->ys <= rectf->ymax && te->ys + UI_UNIT_Y >= rectf->ymin) { + if (gesture_mode == GESTURE_MODAL_SELECT) { + tselem->flag |= TSE_SELECTED; + } + else { + tselem->flag &= ~TSE_SELECTED; + } + } + + /* Look at its children. */ + if ((tselem->flag & TSE_CLOSED) == 0) { + for (te = te->subtree.first; te; te = te->next) { + outliner_item_border_select(scene, soops, rectf, te, gesture_mode); + } + } + return; +} + +static int outliner_border_select_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + SpaceOops *soops= CTX_wm_space_outliner(C); + ARegion *ar= CTX_wm_region(C); + TreeElement *te; + rcti rect; + rctf rectf; + int gesture_mode= RNA_int_get(op->ptr, "gesture_mode"); + + rect.xmin= RNA_int_get(op->ptr, "xmin"); + rect.ymin= RNA_int_get(op->ptr, "ymin"); + UI_view2d_region_to_view(&ar->v2d, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin); + + rect.xmax= RNA_int_get(op->ptr, "xmax"); + rect.ymax= RNA_int_get(op->ptr, "ymax"); + UI_view2d_region_to_view(&ar->v2d, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax); + + for(te= soops->tree.first; te; te= te->next) { + outliner_item_border_select(scene, soops, &rectf, te, gesture_mode); + } + + WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene); + ED_region_tag_redraw(ar); + + return OPERATOR_FINISHED; +} + +void OUTLINER_OT_select_border(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Border Select"; + ot->idname= "OUTLINER_OT_select_border"; + ot->description= "Use box selection to select tree elements"; + + /* api callbacks */ + ot->invoke= WM_border_select_invoke; + ot->exec= outliner_border_select_exec; + ot->modal= WM_border_select_modal; + ot->cancel= WM_border_select_cancel; + + ot->poll= ED_operator_outliner_active; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* rna */ + WM_operator_properties_gesture_border(ot, FALSE); +} + +/* ****************************************************** */ diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 176ffd91e3b..511f1524fae 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -143,7 +143,7 @@ static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[ case SEQ_COLOR: if (colvars->col) { - rgb_float_to_byte(colvars->col, col); + rgb_float_to_uchar(col, colvars->col); } else { col[0] = col[1] = col[2] = 128; } diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index 17cb1ce2995..2d77ab20808 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -1966,7 +1966,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, unsigned char col[4]; float col_f[4]; glGetFloatv(GL_CURRENT_COLOR, col_f); /* incase this is not set below */ - rgb_float_to_byte(col_f, col); + rgb_float_to_uchar(col, col_f); col[3]= 255; if (v3d->zbuf) glDisable(GL_DEPTH_TEST); diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index f2c8fafb8b8..061a9f5a300 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -352,11 +352,8 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O Gtexdraw.islit= GPU_scene_object_lights(scene, ob, v3d->lay, rv3d->viewmat, !rv3d->is_persp); } - obcol[0]= CLAMPIS(ob->col[0]*255, 0, 255); - obcol[1]= CLAMPIS(ob->col[1]*255, 0, 255); - obcol[2]= CLAMPIS(ob->col[2]*255, 0, 255); - obcol[3]= CLAMPIS(ob->col[3]*255, 0, 255); - + rgba_float_to_uchar(obcol, ob->col); + glCullFace(GL_BACK); glEnable(GL_CULL_FACE); if(solidtex || v3d->drawtype==OB_TEXTURE) istex= 1; else istex= 0; diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index a1c8ef953cb..2e4a1e9e348 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -4174,7 +4174,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if(v3d->zbuf) glDepthMask(1); if((ma) && (part->draw_col == PART_DRAW_COL_MAT)) { - rgb_float_to_byte(&(ma->r), tcol); + rgb_float_to_uchar(tcol, &(ma->r)); copy_v3_v3(ma_col, &ma->r); } @@ -6226,7 +6226,7 @@ static void drawRBpivot(bRigidBodyJointConstraint *data) float curcol[4]; unsigned char tcol[4]; glGetFloatv(GL_CURRENT_COLOR, curcol); - rgb_float_to_byte(curcol, tcol); + rgb_float_to_uchar(tcol, curcol); tcol[3]= 255; eul_to_mat4(mat,&data->axX); @@ -6849,7 +6849,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) float curcol[4]; unsigned char tcol[4]; glGetFloatv(GL_CURRENT_COLOR, curcol); - rgb_float_to_byte(curcol, tcol); + rgb_float_to_uchar(tcol, curcol); tcol[3]= 255; view3d_cached_text_draw_add(zero, ob->id.name+2, 10, 0, tcol); } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index ad85ff6dea8..1fa50124a28 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1097,7 +1097,9 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); setlinestyle(0); + UI_ThemeColor(TH_BACK); + glRectf(x1i, y1i, x2i, y2i); #ifdef VIEW3D_CAMERA_BORDER_HACK @@ -1109,6 +1111,13 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) #endif setlinestyle(3); + + /* outer line not to confuse with object selecton */ + if (v3d->flag2 & V3D_LOCK_CAMERA) { + UI_ThemeColor(TH_REDALERT); + glRectf(x1i - 1, y1i - 1, x2i + 1, y2i + 1); + } + UI_ThemeColor(TH_WIRE); glRectf(x1i, y1i, x2i, y2i); @@ -2889,6 +2898,7 @@ static void view3d_main_area_draw_info(const bContext *C, ARegion *ar, const cha else if(U.uiflag & USER_SHOW_VIEWPORTNAME) { draw_viewport_name(ar, v3d); } + if (grid_unit) { /* draw below the viewport name */ char numstr[32]= ""; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 8581a43eb41..4240931989c 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5387,7 +5387,15 @@ static void createTransNodeData(bContext *C, TransInfo *t) /* *** CLIP EDITOR *** */ +enum { + transDataTracking_ModeTracks = 0, + transDataTracking_ModeCurves = 1, +} transDataTracking_Mode; + typedef struct TransDataTracking { + int mode, flag; + + /* tracks transformation from main window */ int area; float *relative, *loc; float soffset[2], srelative[2]; @@ -5396,6 +5404,10 @@ typedef struct TransDataTracking { float (*smarkers)[2]; int markersnr; MovieTrackingMarker *markers; + + /* marker transformation from curves editor */ + float *prev_pos, scale; + short coord; } TransDataTracking; static void markerToTransDataInit(TransData *td, TransData2D *td2d, @@ -5403,6 +5415,8 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, { int anchor = area==TRACK_AREA_POINT && off; + tdt->mode = transDataTracking_ModeTracks; + if(anchor) { td2d->loc[0] = rel[0]; /* hold original location */ td2d->loc[1] = rel[1]; @@ -5457,8 +5471,7 @@ static void trackToTransData(SpaceClip *sc, TransData *td, TransData2D *td2d, { MovieTrackingMarker *marker= BKE_tracking_ensure_marker(track, sc->user.framenr); - track->transflag= marker->flag; - + tdt->flag= marker->flag; marker->flag&= ~(MARKER_DISABLED|MARKER_TRACKED); markerToTransDataInit(td++, td2d++, tdt++, track, TRACK_AREA_POINT, track->offset, marker->pos, track->offset); @@ -5487,7 +5500,7 @@ static void transDataTrackingFree(TransInfo *t) } } -static void createTransTrackingData(bContext *C, TransInfo *t) +static void createTransTrackingTracksData(bContext *C, TransInfo *t) { TransData *td; TransData2D *td2d; @@ -5499,11 +5512,6 @@ static void createTransTrackingData(bContext *C, TransInfo *t) TransDataTracking *tdt; int framenr = sc->user.framenr; - if(!clip || !BKE_movieclip_has_frame(clip, &sc->user)) { - t->total = 0; - return; - } - /* count */ t->total = 0; @@ -5512,13 +5520,11 @@ static void createTransTrackingData(bContext *C, TransInfo *t) if(TRACK_VIEW_SELECTED(sc, track) && (track->flag&TRACK_LOCKED)==0) { marker= BKE_tracking_get_marker(track, framenr); - if(marker) { - t->total++; /* offset */ + t->total++; /* offset */ - if(track->flag&SELECT) t->total++; - if(track->pat_flag&SELECT) t->total+= 2; - if(track->search_flag&SELECT) t->total+= 2; - } + if(track->flag&SELECT) t->total++; + if(track->pat_flag&SELECT) t->total+= 2; + if(track->search_flag&SELECT) t->total+= 2; } track = track->next; @@ -5568,6 +5574,194 @@ static void createTransTrackingData(bContext *C, TransInfo *t) } } +static void markerToTransCurveDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt, + MovieTrackingMarker *marker, MovieTrackingMarker *prev_marker, + short coord, float size) +{ + float frames_delta = (marker->framenr - prev_marker->framenr); + + tdt->flag = marker->flag; + marker->flag &= ~MARKER_TRACKED; + + tdt->mode = transDataTracking_ModeCurves; + tdt->coord = coord; + tdt->scale = 1.0f / size * frames_delta; + tdt->prev_pos = prev_marker->pos; + + /* calculate values depending on marker's speed */ + td2d->loc[0] = marker->framenr; + td2d->loc[1] = (marker->pos[coord] - prev_marker->pos[coord]) * size / frames_delta; + td2d->loc[2] = 0.0f; + + td2d->loc2d = marker->pos; /* current location */ + + td->flag = 0; + td->loc = td2d->loc; + VECCOPY(td->center, td->loc); + VECCOPY(td->iloc, td->loc); + + memset(td->axismtx, 0, sizeof(td->axismtx)); + td->axismtx[2][2] = 1.0f; + + td->ext= NULL; td->val= NULL; + + td->flag |= TD_SELECTED; + td->dist= 0.0; + + unit_m3(td->mtx); + unit_m3(td->smtx); +} + +static void createTransTrackingCurvesData(bContext *C, TransInfo *t) +{ + TransData *td; + TransData2D *td2d; + SpaceClip *sc = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip(sc); + ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); + MovieTrackingTrack *track; + MovieTrackingMarker *marker, *prev_marker; + TransDataTracking *tdt; + int i, width, height; + + BKE_movieclip_get_size(clip, &sc->user, &width, &height); + + /* count */ + t->total = 0; + + track = tracksbase->first; + while(track) { + if(TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED)==0) { + for(i = 1; i < track->markersnr; i++) { + marker = &track->markers[i]; + prev_marker = &track->markers[i-1]; + + if((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED)) + continue; + + if(marker->flag & MARKER_GRAPH_SEL_X) + t->total += 1; + + if(marker->flag & MARKER_GRAPH_SEL_Y) + t->total += 1; + } + } + + track = track->next; + } + + if(t->total==0) + return; + + td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransTracking TransData"); + td2d = t->data2d = MEM_callocN(t->total*sizeof(TransData2D), "TransTracking TransData2D"); + tdt = t->customData = MEM_callocN(t->total*sizeof(TransDataTracking), "TransTracking TransDataTracking"); + + t->customFree = transDataTrackingFree; + + /* create actual data */ + track = tracksbase->first; + while(track) { + if(TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED)==0) { + for(i = 1; i < track->markersnr; i++) { + marker = &track->markers[i]; + prev_marker = &track->markers[i-1]; + + if((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED)) + continue; + + if(marker->flag & MARKER_GRAPH_SEL_X) { + markerToTransCurveDataInit(td, td2d, tdt, marker, &track->markers[i-1], 0, width); + td += 1; + td2d += 1; + tdt += 1; + } + + if(marker->flag & MARKER_GRAPH_SEL_Y) { + markerToTransCurveDataInit(td, td2d, tdt, marker, &track->markers[i-1], 1, height); + + td += 1; + td2d += 1; + tdt += 1; + } + } + } + + track = track->next; + } +} + +static void createTransTrackingData(bContext *C, TransInfo *t) +{ + ARegion *ar = CTX_wm_region(C); + SpaceClip *sc = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip(sc); + + if(!clip || !BKE_movieclip_has_frame(clip, &sc->user)) { + t->total = 0; + return; + } + + if(ar->regiontype == RGN_TYPE_PREVIEW) { + /* transformation was called from graph editor */ + createTransTrackingCurvesData(C, t); + } + else { + createTransTrackingTracksData(C, t); + } +} + +static void cancelTransTracking(TransInfo *t) +{ + TransDataTracking *tdt = t->customData; + SpaceClip *sc= t->sa->spacedata.first; + MovieClip *clip= ED_space_clip(sc); + ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); + MovieTrackingTrack *track; + MovieTrackingMarker *marker; + int a, framenr = sc->user.framenr; + + if(tdt->mode == transDataTracking_ModeTracks) { + track = tracksbase->first; + while(track) { + if(TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED)==0) { + marker = BKE_tracking_get_marker(track, framenr); + marker->flag = tdt->flag; + + tdt++; + + if(track->flag&SELECT) tdt++; + if(track->pat_flag&SELECT) tdt += 2; + if(track->search_flag&SELECT) tdt += 2; + } + + track = track->next; + } + } + else if(tdt->mode == transDataTracking_ModeCurves) { + MovieTrackingMarker *prev_marker; + + track = tracksbase->first; + while(track) { + if(TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED)==0) { + for(a = 1; a < track->markersnr; a++) { + marker = &track->markers[a]; + prev_marker = &track->markers[a-1]; + + if((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED)) + continue; + + if(marker->flag & (MARKER_GRAPH_SEL_X|MARKER_GRAPH_SEL_Y)) { + marker->flag = tdt->flag; + } + } + } + + track = track->next; + } + } +} + void flushTransTracking(TransInfo *t) { TransData *td; @@ -5575,36 +5769,44 @@ void flushTransTracking(TransInfo *t) TransDataTracking *tdt; int a; + if(t->state == TRANS_CANCEL) + cancelTransTracking(t); + /* flush to 2d vector from internally used 3d vector */ for(a=0, td= t->data, td2d= t->data2d, tdt= t->customData; a<t->total; a++, td2d++, td++, tdt++) { - if(t->flag&T_ALT_TRANSFORM) { - if(tdt->area==TRACK_AREA_POINT && tdt->relative) { - float d[2], d2[2]; - - if(!tdt->smarkers) { - tdt->smarkers= MEM_callocN(sizeof(*tdt->smarkers)*tdt->markersnr, "flushTransTracking markers"); - for(a= 0; a<tdt->markersnr; a++) - copy_v2_v2(tdt->smarkers[a], tdt->markers[a].pos); - } + if(tdt->mode == transDataTracking_ModeTracks) { + if(t->flag&T_ALT_TRANSFORM) { + if(tdt->area==TRACK_AREA_POINT && tdt->relative) { + float d[2], d2[2]; + + if(!tdt->smarkers) { + tdt->smarkers= MEM_callocN(sizeof(*tdt->smarkers)*tdt->markersnr, "flushTransTracking markers"); + for(a= 0; a<tdt->markersnr; a++) + copy_v2_v2(tdt->smarkers[a], tdt->markers[a].pos); + } - sub_v2_v2v2(d, td2d->loc, tdt->soffset); - sub_v2_v2(d, tdt->srelative); + sub_v2_v2v2(d, td2d->loc, tdt->soffset); + sub_v2_v2(d, tdt->srelative); - sub_v2_v2v2(d2, td2d->loc, tdt->srelative); + sub_v2_v2v2(d2, td2d->loc, tdt->srelative); - for(a= 0; a<tdt->markersnr; a++) - add_v2_v2v2(tdt->markers[a].pos, tdt->smarkers[a], d2); + for(a= 0; a<tdt->markersnr; a++) + add_v2_v2v2(tdt->markers[a].pos, tdt->smarkers[a], d2); - negate_v2_v2(td2d->loc2d, d); + negate_v2_v2(td2d->loc2d, d); + } } - } - if(tdt->area!=TRACK_AREA_POINT || tdt->relative==0) { - td2d->loc2d[0] = td2d->loc[0]; - td2d->loc2d[1] = td2d->loc[1]; + if(tdt->area!=TRACK_AREA_POINT || tdt->relative==0) { + td2d->loc2d[0] = td2d->loc[0]; + td2d->loc2d[1] = td2d->loc[1]; - if(tdt->relative) - sub_v2_v2(td2d->loc2d, tdt->relative); + if(tdt->relative) + sub_v2_v2(td2d->loc2d, tdt->relative); + } + } + else if(tdt->mode == transDataTracking_ModeCurves) { + td2d->loc2d[tdt->coord] = tdt->prev_pos[tdt->coord] + td2d->loc[1] * tdt->scale; } } } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index e917b7d4c96..4073081ffc2 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -644,24 +644,11 @@ static void recalcData_clip(TransInfo *t) ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); MovieTrackingTrack *track; - if(t->state == TRANS_CANCEL) { - track= tracksbase->first; - while(track) { - if(TRACK_VIEW_SELECTED(sc, track)) { - MovieTrackingMarker *marker= BKE_tracking_ensure_marker(track, sc->user.framenr); - - marker->flag= track->transflag; - } - - track= track->next; - } - } - flushTransTracking(t); track= tracksbase->first; while(track) { - if(TRACK_VIEW_SELECTED(sc, track)) { + if(TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED)==0) { if (t->mode == TFM_TRANSLATION) { if(TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) BKE_tracking_clamp_track(track, CLAMP_PAT_POS); diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index c468da6b937..60886f2a713 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -112,7 +112,7 @@ static int ED_operator_uvedit_can_uv_sculpt(struct bContext *C) return ED_space_image_show_uvedit(sima, obedit) && !(toolsettings->use_uv_sculpt); } -static int ED_operator_uvmap_mesh(bContext *C) +static int UNUSED_FUNCTION(ED_operator_uvmap_mesh)(bContext *C) { Object *ob= CTX_data_active_object(C); diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 442309ccf7a..7e086716d3e 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -164,19 +164,6 @@ MINLINE unsigned char dither_value(unsigned short v_in, DitherContext *di, int i /************************* Generic Buffer Conversion *************************/ -MINLINE void byte_to_float_v4(float f[4], const uchar b[4]) -{ - f[0]= b[0] * (1.0f/255.0f); - f[1]= b[1] * (1.0f/255.0f); - f[2]= b[2] * (1.0f/255.0f); - f[3]= b[3] * (1.0f/255.0f); -} - -MINLINE void float_to_byte_v4(uchar b[4], const float f[4]) -{ - F4TOCHAR4(f, b); -} - MINLINE void ushort_to_byte_v4(uchar b[4], const unsigned short us[4]) { b[0]= USHORTTOUCHAR(us[0]); @@ -233,7 +220,7 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, if(profile_to == profile_from) { /* no color space conversion */ for(x = 0; x < width; x++, from+=3, to+=4) { - F3TOCHAR3(from, to); + rgb_float_to_uchar(to, from); to[3] = 255; } } @@ -241,7 +228,7 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, /* convert from linear to sRGB */ for(x = 0; x < width; x++, from+=3, to+=4) { linearrgb_to_srgb_v3_v3(tmp, from); - F3TOCHAR3(tmp, to); + rgb_float_to_uchar(to, tmp); to[3] = 255; } } @@ -249,7 +236,7 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, /* convert from sRGB to linear */ for(x = 0; x < width; x++, from+=3, to+=4) { srgb_to_linearrgb_v3_v3(tmp, from); - F3TOCHAR3(tmp, to); + rgb_float_to_uchar(to, tmp); to[3] = 255; } } @@ -267,7 +254,7 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, } else { for(x = 0; x < width; x++, from+=4, to+=4) - float_to_byte_v4(to, from); + rgba_float_to_uchar(to, from); } } else if(profile_to == IB_PROFILE_SRGB) { @@ -316,13 +303,13 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, else if(predivide) { for(x = 0; x < width; x++, from+=4, to+=4) { srgb_to_linearrgb_predivide_v4(tmp, from); - float_to_byte_v4(to, tmp); + rgba_float_to_uchar(to, tmp); } } else { for(x = 0; x < width; x++, from+=4, to+=4) { srgb_to_linearrgb_v4(tmp, from); - float_to_byte_v4(to, tmp); + rgba_float_to_uchar(to, tmp); } } } @@ -358,7 +345,7 @@ void IMB_buffer_float_from_byte(float *rect_to, const uchar *rect_from, if(profile_to == profile_from) { /* no color space conversion */ for(x = 0; x < width; x++, from+=4, to+=4) - byte_to_float_v4(to, from); + rgba_uchar_to_float(to, from); } else if(profile_to == IB_PROFILE_LINEAR_RGB) { /* convert sRGB to linear */ @@ -377,13 +364,13 @@ void IMB_buffer_float_from_byte(float *rect_to, const uchar *rect_from, /* convert linear to sRGB */ if(predivide) { for(x = 0; x < width; x++, from+=4, to+=4) { - byte_to_float_v4(tmp, from); + rgba_uchar_to_float(tmp, from); linearrgb_to_srgb_predivide_v4(to, tmp); } } else { for(x = 0; x < width; x++, from+=4, to+=4) { - byte_to_float_v4(tmp, from); + rgba_uchar_to_float(tmp, from); linearrgb_to_srgb_v4(to, tmp); } } @@ -502,16 +489,16 @@ void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from, /* convert to sRGB to linear */ if(predivide) { for(x = 0; x < width; x++, from+=4, to+=4) { - byte_to_float_v4(tmp, from); + rgba_uchar_to_float(tmp, from); srgb_to_linearrgb_predivide_v4(tmp, tmp); - float_to_byte_v4(to, tmp); + rgba_float_to_uchar(to, tmp); } } else { for(x = 0; x < width; x++, from+=4, to+=4) { - byte_to_float_v4(tmp, from); + rgba_uchar_to_float(tmp, from); srgb_to_linearrgb_v4(tmp, tmp); - float_to_byte_v4(to, tmp); + rgba_float_to_uchar(to, tmp); } } } @@ -519,16 +506,16 @@ void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from, /* convert from linear to sRGB */ if(predivide) { for(x = 0; x < width; x++, from+=4, to+=4) { - byte_to_float_v4(tmp, from); + rgba_uchar_to_float(tmp, from); linearrgb_to_srgb_predivide_v4(tmp, tmp); - float_to_byte_v4(to, tmp); + rgba_float_to_uchar(to, tmp); } } else { for(x = 0; x < width; x++, from+=4, to+=4) { - byte_to_float_v4(tmp, from); + rgba_uchar_to_float(tmp, from); linearrgb_to_srgb_v4(tmp, tmp); - float_to_byte_v4(to, tmp); + rgba_float_to_uchar(to, tmp); } } } diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index a8b3a7183cf..6ab8b5524ff 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -91,12 +91,8 @@ typedef struct MovieTrackingTrack { float bundle_pos[3]; /* reconstructed position */ float error; /* average track reprojection error */ - int pad; - /* ** UI editing ** */ int flag, pat_flag, search_flag; /* flags (selection, ...) */ - short transflag; /* transform flags */ - char pad3[2]; float color[3]; /* custom color for track */ /* tracking algorithm to use; can be KLT or SAD */ @@ -213,7 +209,8 @@ enum { /* MovieTrackingMarker->flag */ #define MARKER_DISABLED (1<<0) #define MARKER_TRACKED (1<<1) -#define MARKER_GRAPH_SEL (1<<2) +#define MARKER_GRAPH_SEL_X (1<<2) +#define MARKER_GRAPH_SEL_Y (1<<3) /* MovieTrackingTrack->flag */ #define TRACK_HAS_BUNDLE (1<<1) diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript index 1f04e81707c..60818680d0c 100644 --- a/source/blender/makesrna/intern/SConscript +++ b/source/blender/makesrna/intern/SConscript @@ -101,6 +101,10 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'): if env['WITH_BF_INTERNATIONAL']: defs.append('WITH_INTERNATIONAL') +if not env['BF_DEBUG']: + defs.append('NDEBUG') + + makesrna_tool.Append(CPPDEFINES=defs) makesrna_tool.Append (CPPPATH = Split(incs)) diff --git a/source/blender/makesrna/intern/rna_controller.c b/source/blender/makesrna/intern/rna_controller.c index 5278c1e3532..7dfb3597a29 100644 --- a/source/blender/makesrna/intern/rna_controller.c +++ b/source/blender/makesrna/intern/rna_controller.c @@ -48,6 +48,7 @@ EnumPropertyItem controller_type_items[] ={ #ifdef RNA_RUNTIME #include "BKE_sca.h" +#include "DNA_actuator_types.h" static struct StructRNA* rna_Controller_refine(struct PointerRNA *ptr) { @@ -132,6 +133,18 @@ static void rna_Controller_state_number_set(struct PointerRNA *ptr, const int va cont->state_mask = (1 << (value - 1)); } +static void rna_Controller_actuators_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + bController *cont = (bController *)ptr->data; + rna_iterator_array_begin(iter, cont->links, sizeof(bActuator *), (int)cont->totlinks, 0, NULL); +} + +static int rna_Controller_actuators_length(PointerRNA *ptr) +{ + bController *cont = (bController *)ptr->data; + return (int) cont->totlinks; +} + #if 0 /* editable is set to false, comment for now. */ static void rna_Controller_state_get(PointerRNA *ptr, int *values) { @@ -212,6 +225,12 @@ void RNA_def_controller(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_BOOKMARKS, 1); RNA_def_property_update(prop, NC_LOGIC, NULL); + prop= RNA_def_property(srna, "actuators", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "links", NULL); + RNA_def_property_struct_type(prop, "Actuator"); + RNA_def_property_ui_text(prop, "Actuators", "The list containing the actuators connected to the controller"); + RNA_def_property_collection_funcs(prop, "rna_Controller_actuators_begin", "rna_iterator_array_next", "rna_iterator_array_end", "rna_iterator_array_dereference_get", "rna_Controller_actuators_length", NULL, NULL, NULL); + /* State */ // array of OB_MAX_STATES diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index d8a78ac1f97..93aec352271 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -63,6 +63,7 @@ #include "BKE_font.h" #include "BKE_mball.h" #include "BKE_modifier.h" +#include "BKE_cdderivedmesh.h" #include "DNA_mesh_types.h" #include "DNA_scene_types.h" @@ -470,6 +471,44 @@ int rna_Object_is_modified(Object *ob, Scene *scene, int settings) return object_is_modified(scene, ob) & settings; } +#ifndef NDEBUG +void rna_Object_dm_info(struct Object *ob, int type, char *result) +{ + DerivedMesh *dm = NULL; + int dm_release = FALSE; + char *ret = NULL; + + result[0] = '\0'; + + switch(type) { + case 0: + if (ob->type == OB_MESH) { + dm = CDDM_from_mesh(ob->data, ob); + ret = DM_debug_info(dm); + dm_release = TRUE; + } + break; + case 1: + dm = ob->derivedDeform; + break; + case 2: + dm = ob->derivedFinal; + break; + } + + if (dm) { + ret = DM_debug_info(dm); + if (dm_release) { + dm->release(dm); + } + if (ret) { + strcpy(result, ret); + MEM_freeN(ret); + } + } +} +#endif /* NDEBUG */ + #else void RNA_api_object(StructRNA *srna) @@ -483,6 +522,15 @@ void RNA_api_object(StructRNA *srna) {0, NULL, 0, NULL, NULL} }; +#ifndef NDEBUG + static EnumPropertyItem mesh_dm_info_items[] = { + {0, "SOURCE", 0, "Source", "Source mesh"}, + {1, "DEFORM", 0, "Deform", "Objects deform mesh"}, + {2, "FINAL", 0, "Final", "Objects final mesh"}, + {0, NULL, 0, NULL, NULL} + }; +#endif + /* mesh */ func= RNA_def_function(srna, "to_mesh", "rna_Object_to_mesh"); RNA_def_function_ui_description(func, "Create a Mesh datablock with modifiers applied"); @@ -585,6 +633,20 @@ void RNA_api_object(StructRNA *srna) RNA_def_property_flag(parm, PROP_REQUIRED); parm= RNA_def_boolean(func, "result", 0, "", "Object visibility"); RNA_def_function_return(func, parm); + + +#ifndef NDEBUG + /* mesh */ + func= RNA_def_function(srna, "dm_info", "rna_Object_dm_info"); + RNA_def_function_ui_description(func, "Returns a string for derived mesh data"); + + parm= RNA_def_enum(func, "type", mesh_dm_info_items, 0, "", "Modifier settings to apply"); + RNA_def_property_flag(parm, PROP_REQUIRED); + /* weak!, no way to return dynamic string type */ + parm= RNA_def_string(func, "result", "result", 1024, "result", ""); + RNA_def_property_flag(parm, PROP_THICK_WRAP); /* needed for string return value */ + RNA_def_function_output(func, parm); +#endif /* NDEBUG */ } diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 7c30bc21a69..a54a61b8d09 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -889,6 +889,7 @@ static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_audiocodecType_itemf #endif #endif +#ifdef WITH_FFMPEG static void rna_FFmpegSettings_lossless_output_set(PointerRNA *ptr, int value) { Scene *scene = (Scene *) ptr->id.data; @@ -898,10 +899,9 @@ static void rna_FFmpegSettings_lossless_output_set(PointerRNA *ptr, int value) rd->ffcodecdata.flags |= FFMPEG_LOSSLESS_OUTPUT; else rd->ffcodecdata.flags &= ~FFMPEG_LOSSLESS_OUTPUT; -#ifdef WITH_FFMPEG ffmpeg_verify_lossless_format(rd, &rd->im_format); -#endif } +#endif static int rna_RenderSettings_active_layer_index_get(PointerRNA *ptr) { diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index c3c84c66567..67304997571 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -476,12 +476,12 @@ static void rna_def_particle_edit(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Brush", ""); prop= RNA_def_property(srna, "draw_step", PROP_INT, PROP_NONE); - RNA_def_property_range(prop, 2, 10); + RNA_def_property_range(prop, 1, 10); RNA_def_property_ui_text(prop, "Steps", "How many steps to draw the path with"); RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_ParticleEdit_redo"); prop= RNA_def_property(srna, "fade_frames", PROP_INT, PROP_NONE); - RNA_def_property_range(prop, 2, 100); + RNA_def_property_range(prop, 1, 100); RNA_def_property_ui_text(prop, "Frames", "How many frames to fade"); RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_ParticleEdit_update"); diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c index 6459c145a3a..4413eee9395 100644 --- a/source/blender/makesrna/intern/rna_sensor.c +++ b/source/blender/makesrna/intern/rna_sensor.c @@ -61,6 +61,7 @@ EnumPropertyItem sensor_type_items[] ={ #ifdef RNA_RUNTIME #include "BKE_sca.h" +#include "DNA_controller_types.h" static StructRNA* rna_Sensor_refine(struct PointerRNA *ptr) { @@ -125,6 +126,19 @@ static void rna_Sensor_type_set(struct PointerRNA *ptr, int value) } /* Always keep in alphabetical order */ + +static void rna_Sensor_controllers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + bSensor *sens = (bSensor *)ptr->data; + rna_iterator_array_begin(iter, sens->links, sizeof(bController *), (int)sens->totlinks, 0, NULL); +} + +static int rna_Sensor_controllers_length(PointerRNA *ptr) +{ + bSensor *sens = (bSensor *)ptr->data; + return (int) sens->totlinks; +} + EnumPropertyItem *rna_Sensor_type_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free) { EnumPropertyItem *item= NULL; @@ -327,6 +341,13 @@ static void rna_def_sensor(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Tap", "Trigger controllers only for an instant, even while the sensor remains true"); RNA_def_property_update(prop, NC_LOGIC, NULL); + prop= RNA_def_property(srna, "controllers", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "links", NULL); + RNA_def_property_struct_type(prop, "Controller"); + RNA_def_property_ui_text(prop, "Controllers", "The list containing the controllers connected to the sensor"); + RNA_def_property_collection_funcs(prop, "rna_Sensor_controllers_begin", "rna_iterator_array_next", "rna_iterator_array_end", "rna_iterator_array_dereference_get", "rna_Sensor_controllers_length", NULL, NULL, NULL); + + RNA_api_sensor(srna); } diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 4940c53551e..bfb79ea6531 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -7158,8 +7158,25 @@ static PyObject *pyrna_register_class(PyObject *UNUSED(self), PyObject *py_class const char *identifier; PyObject *py_cls_meth; + if (!PyType_Check(py_class)) { + PyErr_Format(PyExc_ValueError, + "register_class(...): " + "expected a class argument, not '%.200s'", Py_TYPE(py_class)->tp_name); + return NULL; + } + if (PyDict_GetItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna)) { - PyErr_SetString(PyExc_AttributeError, "register_class(...): already registered as a subclass"); + PyErr_SetString(PyExc_ValueError, + "register_class(...): " + "already registered as a subclass"); + return NULL; + } + + if (!pyrna_write_check()) { + PyErr_Format(PyExc_RuntimeError, + "register_class(...): " + "can't run in readonly state '%.200s'", + ((PyTypeObject *)py_class)->tp_name); return NULL; } @@ -7284,12 +7301,27 @@ static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_cla StructRNA *srna; PyObject *py_cls_meth; + if (!PyType_Check(py_class)) { + PyErr_Format(PyExc_ValueError, + "register_class(...): " + "expected a class argument, not '%.200s'", Py_TYPE(py_class)->tp_name); + return NULL; + } + /*if (PyDict_GetItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna) == NULL) { PWM_cursor_wait(0); PyErr_SetString(PyExc_ValueError, "unregister_class(): not a registered as a subclass"); return NULL; }*/ + if (!pyrna_write_check()) { + PyErr_Format(PyExc_RuntimeError, + "unregister_class(...): " + "can't run in readonly state '%.200s'", + ((PyTypeObject *)py_class)->tp_name); + return NULL; + } + srna = pyrna_struct_as_srna(py_class, 0, "unregister_class(...):"); if (srna == NULL) return NULL; diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index e19b4a1e669..49bacbaf693 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -2127,7 +2127,8 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T fMagnitude *= len_v3(vN); } - for(xyz=0; xyz<3; xyz++) + if(ntap_bump->fPrevMagnitude > 0.0f) + for(xyz=0; xyz<3; xyz++) ntap_bump->vNacc[xyz] *= fMagnitude / ntap_bump->fPrevMagnitude; ntap_bump->fPrevMagnitude = fMagnitude; diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 630acf3d88a..773af96671a 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -2166,21 +2166,13 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua } } else { - char *col= (char *)(bs->rect + bs->rectx*y + x); + unsigned char *col= (unsigned char *)(bs->rect + bs->rectx*y + x); if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE) && (R.r.color_mgt_flag & R_COLOR_MANAGEMENT)) { - float srgb[3]; - srgb[0]= linearrgb_to_srgb(shr.combined[0]); - srgb[1]= linearrgb_to_srgb(shr.combined[1]); - srgb[2]= linearrgb_to_srgb(shr.combined[2]); - - col[0]= FTOCHAR(srgb[0]); - col[1]= FTOCHAR(srgb[1]); - col[2]= FTOCHAR(srgb[2]); - } else { - col[0]= FTOCHAR(shr.combined[0]); - col[1]= FTOCHAR(shr.combined[1]); - col[2]= FTOCHAR(shr.combined[2]); + linearrgb_to_srgb_uchar3(col, shr.combined); + } + else { + rgb_float_to_uchar(col, shr.combined); } if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) { @@ -2212,9 +2204,7 @@ static void bake_displacement(void *handle, ShadeInput *UNUSED(shi), float dist, col[3]= 1.0f; } else { char *col= (char *)(bs->rect + bs->rectx*y + x); - col[0]= FTOCHAR(disp); - col[1]= FTOCHAR(disp); - col[2]= FTOCHAR(disp); + col[0] = col[1] = col[2] = FTOCHAR(disp); col[3]= 255; } if (bs->rect_mask) { diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index ec4e035068a..3a3be292f07 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3807,6 +3807,7 @@ static void gesture_border_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_assign(keymap, "MARKER_OT_select_border"); WM_modalkeymap_assign(keymap, "NLA_OT_select_border"); WM_modalkeymap_assign(keymap, "NODE_OT_select_border"); + WM_modalkeymap_assign(keymap, "OUTLINER_OT_select_border"); // WM_modalkeymap_assign(keymap, "SCREEN_OT_border_select"); // template WM_modalkeymap_assign(keymap, "SEQUENCER_OT_select_border"); WM_modalkeymap_assign(keymap, "SEQUENCER_OT_view_ghost_border"); diff --git a/source/tests/bl_mesh_modifiers.py b/source/tests/bl_mesh_modifiers.py index 789a4037659..917ccbc0d24 100644 --- a/source/tests/bl_mesh_modifiers.py +++ b/source/tests/bl_mesh_modifiers.py @@ -301,7 +301,7 @@ def mesh_vcol_add(obj, mode=0): face_verts = mesh_bmesh_poly_vertices(poly) poly_cols = mesh_bmesh_poly_elems(poly, col_list) for i, c in enumerate(poly_cols): - c.color = colors[i % 4] + c.color = colors_get(face_verts[i]) else: for i, col in enumerate(vcol_lay.data): face_verts = mesh.faces[i].vertices |