void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *recti) { Scopes *scopes = (Scopes *)but->poin; rctf rect; int i, c; float w, w3, h, alpha, yofs; GLint scissor[4]; float colors[3][3] = MAT3_UNITY; float colorsycc[3][3] = {{1, 0, 1}, {1, 1, 0}, {0, 1, 1}}; float colors_alpha[3][3], colorsycc_alpha[3][3]; /* colors pre multiplied by alpha for speed up */ float min, max; if (scopes == NULL) return; rect.xmin = (float)recti->xmin + 1; rect.xmax = (float)recti->xmax - 1; rect.ymin = (float)recti->ymin + SCOPE_RESIZE_PAD + 2; rect.ymax = (float)recti->ymax - 1; if (scopes->wavefrm_yfac < 0.5f) scopes->wavefrm_yfac = 0.98f; w = BLI_rctf_size_x(&rect) - 7; h = BLI_rctf_size_y(&rect) * scopes->wavefrm_yfac; yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) / 2.0f; w3 = w / 3.0f; /* log scale for alpha */ alpha = scopes->wavefrm_alpha * scopes->wavefrm_alpha; for (c = 0; c < 3; c++) { for (i = 0; i < 3; i++) { colors_alpha[c][i] = colors[c][i] * alpha; colorsycc_alpha[c][i] = colorsycc[c][i] * alpha; } } glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4f(0.f, 0.f, 0.f, 0.3f); uiSetRoundBox(UI_CNR_ALL); uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f); /* need scissor test, waveform can draw outside of boundary */ glGetIntegerv(GL_VIEWPORT, scissor); glScissor(ar->winrct.xmin + (rect.xmin - 1), ar->winrct.ymin + (rect.ymin - 1), (rect.xmax + 1) - (rect.xmin - 1), (rect.ymax + 1) - (rect.ymin - 1)); glColor4f(1.f, 1.f, 1.f, 0.08f); /* draw grid lines here */ for (i = 0; i < 6; i++) { char str[4]; BLI_snprintf(str, sizeof(str), "%-3d", i * 20); str[3] = '\0'; fdrawline(rect.xmin + 22, yofs + (i / 5.f) * h, rect.xmax + 1, yofs + (i / 5.f) * h); BLF_draw_default(rect.xmin + 1, yofs - 5 + (i / 5.f) * h, 0, str, sizeof(str) - 1); /* in the loop because blf_draw reset it */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } /* 3 vertical separation */ if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA) { for (i = 1; i < 3; i++) { fdrawline(rect.xmin + i * w3, rect.ymin, rect.xmin + i * w3, rect.ymax); } } /* separate min max zone on the right */ fdrawline(rect.xmin + w, rect.ymin, rect.xmin + w, rect.ymax); /* 16-235-240 level in case of ITU-R BT601/709 */ glColor4f(1.f, 0.4f, 0.f, 0.2f); if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_YCC_601, SCOPES_WAVEFRM_YCC_709)) { fdrawline(rect.xmin + 22, yofs + h * 16.0f / 255.0f, rect.xmax + 1, yofs + h * 16.0f / 255.0f); fdrawline(rect.xmin + 22, yofs + h * 235.0f / 255.0f, rect.xmin + w3, yofs + h * 235.0f / 255.0f); fdrawline(rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f, rect.xmax + 1, yofs + h * 235.0f / 255.0f); fdrawline(rect.xmin + w3, yofs + h * 240.0f / 255.0f, rect.xmax + 1, yofs + h * 240.0f / 255.0f); } /* 7.5 IRE black point level for NTSC */ if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) fdrawline(rect.xmin, yofs + h * 0.075f, rect.xmax + 1, yofs + h * 0.075f); if (scopes->ok && scopes->waveform_1 != NULL) { /* LUMA (1 channel) */ glBlendFunc(GL_ONE, GL_ONE); glColor3f(alpha, alpha, alpha); if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) { glBlendFunc(GL_ONE, GL_ONE); glPushMatrix(); glEnableClientState(GL_VERTEX_ARRAY); glTranslatef(rect.xmin, yofs, 0.f); glScalef(w, h, 0.f); glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1); glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); glDisableClientState(GL_VERTEX_ARRAY); glPopMatrix(); /* min max */ glColor3f(0.5f, 0.5f, 0.5f); min = yofs + scopes->minmax[0][0] * h; max = yofs + scopes->minmax[0][1] * h; CLAMP(min, rect.ymin, rect.ymax); CLAMP(max, rect.ymin, rect.ymax); fdrawline(rect.xmax - 3, min, rect.xmax - 3, max); } /* RGB / YCC (3 channels) */ else if (ELEM4(scopes->wavefrm_mode, SCOPES_WAVEFRM_RGB, SCOPES_WAVEFRM_YCC_601, SCOPES_WAVEFRM_YCC_709, SCOPES_WAVEFRM_YCC_JPEG)) { int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB); glBlendFunc(GL_ONE, GL_ONE); glPushMatrix(); glEnableClientState(GL_VERTEX_ARRAY); glTranslatef(rect.xmin, yofs, 0.f); glScalef(w3, h, 0.f); glColor3fv((rgb) ? colors_alpha[0] : colorsycc_alpha[0]); glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1); glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); glTranslatef(1.f, 0.f, 0.f); glColor3fv((rgb) ? colors_alpha[1] : colorsycc_alpha[1]); glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_2); glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); glTranslatef(1.f, 0.f, 0.f); glColor3fv((rgb) ? colors_alpha[2] : colorsycc_alpha[2]); glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_3); glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); glDisableClientState(GL_VERTEX_ARRAY); glPopMatrix(); /* min max */ for (c = 0; c < 3; c++) { if (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB) glColor3f(colors[c][0] * 0.75f, colors[c][1] * 0.75f, colors[c][2] * 0.75f); else glColor3f(colorsycc[c][0] * 0.75f, colorsycc[c][1] * 0.75f, colorsycc[c][2] * 0.75f); min = yofs + scopes->minmax[c][0] * h; max = yofs + scopes->minmax[c][1] * h; CLAMP(min, rect.ymin, rect.ymax); CLAMP(max, rect.ymin, rect.ymax); fdrawline(rect.xmin + w + 2 + c * 2, min, rect.xmin + w + 2 + c * 2, max); } } } /* outline, scale gripper */ draw_scope_end(&rect, scissor); }
static void borderselect_action(bAnimContext *ac, const rcti rect, short mode, short selectmode) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; KeyframeEditData ked; KeyframeEditFunc ok_cb, select_cb; View2D *v2d = &ac->ar->v2d; rctf rectf; float ymin = 0, ymax = (float)(-ACHANNEL_HEIGHT_HALF(ac)); /* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */ UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin + 2, &rectf.xmin, &rectf.ymin); UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax - 2, &rectf.xmax, &rectf.ymax); /* filter data */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* get beztriple editing/validation funcs */ select_cb = ANIM_editkeyframes_select(selectmode); if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE); else ok_cb = NULL; /* init editing data */ memset(&ked, 0, sizeof(KeyframeEditData)); /* loop over data, doing border select */ for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); /* get new vertical minimum extent of channel */ ymin = ymax - ACHANNEL_STEP(ac); /* set horizontal range (if applicable) */ if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) { /* if channel is mapped in NLA, apply correction */ if (adt) { ked.iterflags &= ~(KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); ked.f1 = BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP); ked.f2 = BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP); } else { ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */ ked.f1 = rectf.xmin; ked.f2 = rectf.xmax; } } /* perform vertical suitability check (if applicable) */ if ((mode == ACTKEYS_BORDERSEL_FRAMERANGE) || !((ymax < rectf.ymin) || (ymin > rectf.ymax))) { /* loop over data selecting */ switch (ale->type) { #if 0 /* XXX: Keyframes are not currently shown here */ case ANIMTYPE_GPDATABLOCK: { bGPdata *gpd = ale->data; bGPDlayer *gpl; for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { ED_gplayer_frames_select_border(gpl, rectf.xmin, rectf.xmax, selectmode); } break; } #endif case ANIMTYPE_GPLAYER: ED_gplayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode); break; case ANIMTYPE_MASKDATABLOCK: { Mask *mask = ale->data; MaskLayer *masklay; for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { ED_masklayer_frames_select_border(masklay, rectf.xmin, rectf.xmax, selectmode); } break; } case ANIMTYPE_MASKLAYER: ED_masklayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode); break; default: ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL); break; } } /* set minimum extent to be the maximum of the next channel */ ymax = ymin; } /* cleanup */ ANIM_animdata_freelist(&anim_data); }
/* Deselects keyframes in the action editor * - This is called by the deselect all operator, as well as other ones! * * - test: check if select or deselect all * - sel: how to select keyframes (SELECT_*) */ static void deselect_action_keys(bAnimContext *ac, short test, short sel) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; KeyframeEditData ked = {{NULL}}; KeyframeEditFunc test_cb, sel_cb; /* determine type-based settings */ if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS); else filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS); /* filter data */ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* init BezTriple looping data */ test_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED); /* See if we should be selecting or deselecting */ if (test) { for (ale = anim_data.first; ale; ale = ale->next) { if (ale->type == ANIMTYPE_GPLAYER) { if (ED_gplayer_frame_select_check(ale->data)) { sel = SELECT_SUBTRACT; break; } } else if (ale->type == ANIMTYPE_MASKLAYER) { if (ED_masklayer_frame_select_check(ale->data)) { sel = SELECT_SUBTRACT; break; } } else { if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) { sel = SELECT_SUBTRACT; break; } } } } /* convert sel to selectmode, and use that to get editor */ sel_cb = ANIM_editkeyframes_select(sel); /* Now set the flags */ for (ale = anim_data.first; ale; ale = ale->next) { if (ale->type == ANIMTYPE_GPLAYER) ED_gplayer_frame_select_set(ale->data, sel); else if (ale->type == ANIMTYPE_MASKLAYER) ED_masklayer_frame_select_set(ale->data, sel); else ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL); } /* Cleanup */ ANIM_animdata_freelist(&anim_data); }
// TODO: introduce scaling factor for weighting falloff void smooth_fcurve(FCurve *fcu) { BezTriple *bezt; int i, x, totSel = 0; if (fcu->bezt == NULL) { return; } /* first loop through - count how many verts are selected */ bezt = fcu->bezt; for (i = 0; i < fcu->totvert; i++, bezt++) { if (BEZT_ISSEL_ANY(bezt)) totSel++; } /* if any points were selected, allocate tSmooth_Bezt points to work on */ if (totSel >= 3) { tSmooth_Bezt *tarray, *tsb; /* allocate memory in one go */ tsb = tarray = MEM_callocN(totSel * sizeof(tSmooth_Bezt), "tSmooth_Bezt Array"); /* populate tarray with data of selected points */ bezt = fcu->bezt; for (i = 0, x = 0; (i < fcu->totvert) && (x < totSel); i++, bezt++) { if (BEZT_ISSEL_ANY(bezt)) { /* tsb simply needs pointer to vec, and index */ tsb->h1 = &bezt->vec[0][1]; tsb->h2 = &bezt->vec[1][1]; tsb->h3 = &bezt->vec[2][1]; /* advance to the next tsb to populate */ if (x < totSel - 1) tsb++; else break; } } /* calculate the new smoothed F-Curve's with weighted averages: * - this is done with two passes to avoid progressive corruption errors * - uses 5 points for each operation (which stores in the relevant handles) * - previous: w/a ratio = 3:5:2:1:1 * - next: w/a ratio = 1:1:2:5:3 */ /* round 1: calculate smoothing deltas and new values */ tsb = tarray; for (i = 0; i < totSel; i++, tsb++) { /* don't touch end points (otherwise, curves slowly explode, as we don't have enough data there) */ if (ELEM(i, 0, (totSel - 1)) == 0) { const tSmooth_Bezt *tP1 = tsb - 1; const tSmooth_Bezt *tP2 = (i - 2 > 0) ? (tsb - 2) : (NULL); const tSmooth_Bezt *tN1 = tsb + 1; const tSmooth_Bezt *tN2 = (i + 2 < totSel) ? (tsb + 2) : (NULL); const float p1 = *tP1->h2; const float p2 = (tP2) ? (*tP2->h2) : (*tP1->h2); const float c1 = *tsb->h2; const float n1 = *tN1->h2; const float n2 = (tN2) ? (*tN2->h2) : (*tN1->h2); /* calculate previous and next, then new position by averaging these */ tsb->y1 = (3 * p2 + 5 * p1 + 2 * c1 + n1 + n2) / 12; tsb->y3 = (p2 + p1 + 2 * c1 + 5 * n1 + 3 * n2) / 12; tsb->y2 = (tsb->y1 + tsb->y3) / 2; } } /* round 2: apply new values */ tsb = tarray; for (i = 0; i < totSel; i++, tsb++) { /* don't touch end points, as their values weren't touched above */ if (ELEM(i, 0, (totSel - 1)) == 0) { /* y2 takes the average of the 2 points */ *tsb->h2 = tsb->y2; /* handles are weighted between their original values and the averaged values */ *tsb->h1 = ((*tsb->h1) * 0.7f) + (tsb->y1 * 0.3f); *tsb->h3 = ((*tsb->h3) * 0.7f) + (tsb->y3 * 0.3f); } } /* free memory required for tarray */ MEM_freeN(tarray); } /* recalculate handles */ calchandles_fcurve(fcu); }
static void actkeys_select_leftright(bAnimContext *ac, short leftright, short select_mode) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; KeyframeEditFunc ok_cb, select_cb; KeyframeEditData ked = {{NULL}}; Scene *scene = ac->scene; /* if select mode is replace, deselect all keyframes (and channels) first */ if (select_mode == SELECT_REPLACE) { select_mode = SELECT_ADD; /* - deselect all other keyframes, so that just the newly selected remain * - channels aren't deselected, since we don't re-select any as a consequence */ deselect_action_keys(ac, 0, SELECT_SUBTRACT); } /* set callbacks and editing data */ ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE); select_cb = ANIM_editkeyframes_select(select_mode); if (leftright == ACTKEYS_LRSEL_LEFT) { ked.f1 = MINAFRAMEF; ked.f2 = (float)(CFRA + 0.1f); } else { ked.f1 = (float)(CFRA - 0.1f); ked.f2 = MAXFRAMEF; } /* filter data */ if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS); else filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* select keys */ for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); if (adt) { ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } else if (ale->type == ANIMTYPE_GPLAYER) ED_gplayer_frames_select_border(ale->data, ked.f1, ked.f2, select_mode); else if (ale->type == ANIMTYPE_MASKLAYER) ED_masklayer_frames_select_border(ale->data, ked.f1, ked.f2, select_mode); else ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); } /* Sync marker support */ if (select_mode == SELECT_ADD) { SpaceAction *saction = (SpaceAction *)ac->sl; if ((saction) && (saction->flag & SACTION_MARKERS_MOVE)) { ListBase *markers = ED_animcontext_get_markers(ac); TimeMarker *marker; for (marker = markers->first; marker; marker = marker->next) { if (((leftright == ACTKEYS_LRSEL_LEFT) && (marker->frame < CFRA)) || ((leftright == ACTKEYS_LRSEL_RIGHT) && (marker->frame >= CFRA))) { marker->flag |= SELECT; } else { marker->flag &= ~SELECT; } } } } /* Cleanup */ ANIM_animdata_freelist(&anim_data); }
/* Setup motion paths for the given data * - Only used when explicitly calculating paths on bones which may/may not be consider already * * < scene: current scene (for frame ranges, etc.) * < ob: object to add paths for (must be provided) * < pchan: posechannel to add paths for (optional; if not provided, object-paths are assumed) */ bMotionPath *animviz_verify_motionpaths(ReportList *reports, Scene *scene, Object *ob, bPoseChannel *pchan) { bAnimVizSettings *avs; bMotionPath *mpath, **dst; /* sanity checks */ if (ELEM(NULL, scene, ob)) return NULL; /* get destination data */ if (pchan) { /* paths for posechannel - assume that posechannel belongs to the object */ avs= &ob->pose->avs; dst= &pchan->mpath; } else { /* paths for object */ avs= &ob->avs; dst= &ob->mpath; } /* avoid 0 size allocs */ if (avs->path_sf >= avs->path_ef) { BKE_reportf(reports, RPT_ERROR, "Motion Path frame extents invalid for %s (%d to %d).%s\n", (pchan)? pchan->name : ob->id.name, avs->path_sf, avs->path_ef, (avs->path_sf == avs->path_ef)? " Cannot have single-frame paths." : ""); return NULL; } /* if there is already a motionpath, just return that, * provided it's settings are ok (saves extra free+alloc) */ if (*dst != NULL) { int expected_length = avs->path_ef - avs->path_sf; mpath= *dst; /* path is "valid" if length is valid, but must also be of the same length as is being requested */ if ((mpath->start_frame != mpath->end_frame) && (mpath->length > 0)) { /* outer check ensures that we have some curve data for this path */ if (mpath->length == expected_length) { /* return/use this as it is already valid length */ return mpath; } else { /* clear the existing path (as the range has changed), and reallocate below */ animviz_free_motionpath_cache(mpath); } } } else { /* create a new motionpath, and assign it */ mpath= MEM_callocN(sizeof(bMotionPath), "bMotionPath"); *dst= mpath; } /* set settings from the viz settings */ mpath->start_frame= avs->path_sf; mpath->end_frame= avs->path_ef; mpath->length= mpath->end_frame - mpath->start_frame; if (avs->path_bakeflag & MOTIONPATH_BAKE_HEADS) mpath->flag |= MOTIONPATH_FLAG_BHEAD; else mpath->flag &= ~MOTIONPATH_FLAG_BHEAD; /* allocate a cache */ mpath->points= MEM_callocN(sizeof(bMotionPathVert)*mpath->length, "bMotionPathVerts"); /* tag viz settings as currently having some path(s) which use it */ avs->path_bakeflag |= MOTIONPATH_BAKE_HAS_PATHS; /* return it */ return mpath; }
static char *rna_ColorRampElement_path(PointerRNA *ptr) { PointerRNA ramp_ptr; PropertyRNA *prop; char *path = NULL; int index; /* helper macro for use here to try and get the path * - this calls the standard code for getting a path to a texture... */ #define COLRAMP_GETPATH \ { \ prop = RNA_struct_find_property(&ramp_ptr, "elements"); \ if (prop) { \ index = RNA_property_collection_lookup_index(&ramp_ptr, prop, ptr); \ if (index != -1) { \ char *texture_path = rna_ColorRamp_path(&ramp_ptr); \ path = BLI_sprintfN("%s.elements[%d]", texture_path, index); \ MEM_freeN(texture_path); \ } \ } \ } (void)0 /* determine the path from the ID-block to the ramp */ /* FIXME: this is a very slow way to do it, but it will have to suffice... */ if (ptr->id.data) { ID *id = ptr->id.data; switch (GS(id->name)) { case ID_MA: /* 2 cases for material - diffuse and spec */ { Material *ma = (Material *)id; /* try diffuse first */ if (ma->ramp_col) { RNA_pointer_create(id, &RNA_ColorRamp, ma->ramp_col, &ramp_ptr); COLRAMP_GETPATH; } /* try specular if not diffuse */ if (!path && ma->ramp_spec) { RNA_pointer_create(id, &RNA_ColorRamp, ma->ramp_spec, &ramp_ptr); COLRAMP_GETPATH; } break; } case ID_NT: { bNodeTree *ntree = (bNodeTree *)id; bNode *node; for (node = ntree->nodes.first; node; node = node->next) { if (ELEM(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) { RNA_pointer_create(id, &RNA_ColorRamp, node->storage, &ramp_ptr); COLRAMP_GETPATH; } } break; } case ID_LS: { ListBase listbase; LinkData *link; BKE_linestyle_modifier_list_color_ramps((FreestyleLineStyle *)id, &listbase); for (link = (LinkData *)listbase.first; link; link = link->next) { RNA_pointer_create(id, &RNA_ColorRamp, link->data, &ramp_ptr); COLRAMP_GETPATH; } BLI_freelistN(&listbase); break; } default: /* everything else should have a "color_ramp" property */ { /* create pointer to the ID block, and try to resolve "color_ramp" pointer */ RNA_id_pointer_create(id, &ramp_ptr); if (RNA_path_resolve(&ramp_ptr, "color_ramp", &ramp_ptr, &prop)) { COLRAMP_GETPATH; } break; } } } /* cleanup the macro we defined */ #undef COLRAMP_GETPATH return path; }
bp_Book * bp_parseBook(bp_Context * context, xmlNodePtr node) { bp_Book * result = malloc(sizeof(bp_Book)); bp_Node * const parent = &result->node; bp_Node * page; xmlAttrPtr attr; xmlNodePtr child; bp_Page ** pages; st_data * fontSym; context->blockOutside = (void *) &bp_defaultBlockOutsideAttributes; context->blockBorder = (void *) &bp_defaultBlockBorderAttributes; context->blockInside = (void *) &bp_defaultBlockInsideAttributes; context->inlineAttr = (void *) &bp_defaultInlineAttributes; bp_pushBlockOutside(context); bp_pushBlockBorder(context); bp_pushBlockInside(context); bp_pushInline(context); bp_initNode(&result->node, BPE_BOOK); result->width = 528; result->height = 320; result->background = load_texture_cache_deferred("textures/book1.bmp",0); fontSym = st_lookup (bp_fonts, "default"); if (fontSym != NULL) { result->fontFace = fontSym->num; } else { LOG_ERROR("FATAL: default font missing in font symbol table\n"); exit(1); } result->layout = BPL_BOOK; result->blockProgression = BPD_DOWN; result->inlineProgression = BPD_RIGHT; result->pages = NULL; result->nPages = 0; for (attr = node->properties; attr; attr = attr->next) { bp_parseBlockOutsideAttribute(context, context->blockOutside, attr); bp_parseBlockBorderAttribute(context, context->blockBorder, attr); bp_parseBlockInsideAttribute(context, context->blockInside, attr); bp_parseInlineAttribute(context, context->inlineAttr, attr); } for (child = node->children; child; child = child->next) { switch(ELEM(child)) { case BPE_PAGE: result->nPages++; ADD(bp_parsePage(context, child)); break; default: DISCARD(child); } } bp_popBlockOutside(context); bp_popBlockBorder(context); bp_popBlockInside(context); bp_popInline(context); /* create page index */ pages = calloc(result->nPages, sizeof(bp_Page *)); result->pages = pages; for (page = parent->children; page; page = page->next) { *pages++ = (bp_Page *) page; } return result; }
bp_Page * bp_parsePage(bp_Context * context, xmlNodePtr node) { bp_Page * result = malloc(sizeof(bp_Page)); bp_Node * const parent = &result->node; xmlAttrPtr attr; xmlNodePtr child; bp_pushBlockOutside(context); bp_pushBlockBorder(context); bp_pushBlockInside(context); bp_pushInline(context); bp_initNode(&result->node, BPE_PAGE); result->title = NULL; for (attr = node->properties; attr; attr = attr->next) { bp_parseBlockOutsideAttribute(context, context->blockOutside, attr); bp_parseBlockBorderAttribute(context, context->blockBorder, attr); bp_parseBlockInsideAttribute(context, context->blockInside, attr); bp_parseInlineAttribute(context, context->inlineAttr, attr); } for (child = node->children; child; child = child->next) { switch(ELEM(child)) { case BPE_TITLE: if (!result->title) { xmlNodePtr grandchild = child->children; if (ELEM(grandchild) == BPE_TEXT) { int len = strlen(grandchild->content); char * title_string = malloc(++len); memcpy(title_string, grandchild->content, len); result->title = title_string; } else { DISCARD(grandchild); } } else { DISCARD(child); } break; case BPE_REF: bp_parseNavRef(context, child, result); break; case BPE_BLOCK: ADD(bp_parseBlock(context, child)); break; case BPE_IMAGE: ADD(bp_parseImage(context, child)); break; case BPE_TABLE: ADD(bp_parseTable(context, child)); break; case BPE_LABEL: ADD(bp_parseLabel(context, child)); break; default: DISCARD(child); } } bp_popBlockOutside(context); bp_popBlockBorder(context); bp_popBlockInside(context); bp_popInline(context); return result; }
/* bone adding between selected joints */ static int armature_fill_bones_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); bArmature *arm = (obedit) ? obedit->data : NULL; Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); ListBase points = {NULL, NULL}; EditBone *newbone = NULL; int count; /* sanity checks */ if (ELEM(NULL, obedit, arm)) return OPERATOR_CANCELLED; /* loop over all bones, and only consider if visible */ CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) { if (!(ebone->flag & BONE_CONNECTED) && (ebone->flag & BONE_ROOTSEL)) fill_add_joint(ebone, 0, &points); if (ebone->flag & BONE_TIPSEL) fill_add_joint(ebone, 1, &points); } CTX_DATA_END; /* the number of joints determines how we fill: * 1) between joint and cursor (joint=head, cursor=tail) * 2) between the two joints (order is dependent on active-bone/hierarchy) * 3+) error (a smarter method involving finding chains needs to be worked out */ count = BLI_listbase_count(&points); if (count == 0) { BKE_report(op->reports, RPT_ERROR, "No joints selected"); return OPERATOR_CANCELLED; } else if (count == 1) { EditBonePoint *ebp; float curs[3]; /* Get Points - selected joint */ ebp = points.first; /* Get points - cursor (tail) */ invert_m4_m4(obedit->imat, obedit->obmat); mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d)); /* Create a bone */ newbone = add_points_bone(obedit, ebp->vec, curs); } else if (count == 2) { EditBonePoint *ebp_a, *ebp_b; float head[3], tail[3]; short headtail = 0; /* check that the points don't belong to the same bone */ ebp_a = (EditBonePoint *)points.first; ebp_b = ebp_a->next; if (((ebp_a->head_owner == ebp_b->tail_owner) && (ebp_a->head_owner != NULL)) || ((ebp_a->tail_owner == ebp_b->head_owner) && (ebp_a->tail_owner != NULL))) { BKE_report(op->reports, RPT_ERROR, "Same bone selected..."); BLI_freelistN(&points); return OPERATOR_CANCELLED; } /* find which one should be the 'head' */ if ((ebp_a->head_owner && ebp_b->head_owner) || (ebp_a->tail_owner && ebp_b->tail_owner)) { /* use active, nice predictable */ if (arm->act_edbone && ELEM(arm->act_edbone, ebp_a->head_owner, ebp_a->tail_owner)) { headtail = 1; } else if (arm->act_edbone && ELEM(arm->act_edbone, ebp_b->head_owner, ebp_b->tail_owner)) { headtail = 2; } else { /* rule: whichever one is closer to 3d-cursor */ float curs[3]; float dist_sq_a, dist_sq_b; /* get cursor location */ invert_m4_m4(obedit->imat, obedit->obmat); mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d)); /* get distances */ dist_sq_a = len_squared_v3v3(ebp_a->vec, curs); dist_sq_b = len_squared_v3v3(ebp_b->vec, curs); /* compare distances - closer one therefore acts as direction for bone to go */ headtail = (dist_sq_a < dist_sq_b) ? 2 : 1; } } else if (ebp_a->head_owner) { headtail = 1; } else if (ebp_b->head_owner) { headtail = 2; } /* assign head/tail combinations */ if (headtail == 2) { copy_v3_v3(head, ebp_a->vec); copy_v3_v3(tail, ebp_b->vec); } else if (headtail == 1) { copy_v3_v3(head, ebp_b->vec); copy_v3_v3(tail, ebp_a->vec); } /* add new bone and parent it to the appropriate end */ if (headtail) { newbone = add_points_bone(obedit, head, tail); /* do parenting (will need to set connected flag too) */ if (headtail == 2) { /* ebp tail or head - tail gets priority */ if (ebp_a->tail_owner) newbone->parent = ebp_a->tail_owner; else newbone->parent = ebp_a->head_owner; } else { /* ebp_b tail or head - tail gets priority */ if (ebp_b->tail_owner) newbone->parent = ebp_b->tail_owner; else newbone->parent = ebp_b->head_owner; } /* don't set for bone connecting two head points of bones */ if (ebp_a->tail_owner || ebp_b->tail_owner) { newbone->flag |= BONE_CONNECTED; } } } else { /* FIXME.. figure out a method for multiple bones */ BKE_reportf(op->reports, RPT_ERROR, "Too many points selected: %d", count); BLI_freelistN(&points); return OPERATOR_CANCELLED; } if (newbone) { ED_armature_edit_deselect_all(obedit); arm->act_edbone = newbone; newbone->flag |= BONE_TIPSEL; } /* updates */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit); /* free points */ BLI_freelistN(&points); return OPERATOR_FINISHED; }
static int armature_merge_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); bArmature *arm = (obedit) ? obedit->data : NULL; short type = RNA_enum_get(op->ptr, "type"); /* sanity checks */ if (ELEM(NULL, obedit, arm)) return OPERATOR_CANCELLED; /* for now, there's only really one type of merging that's performed... */ if (type == 1) { /* go down chains, merging bones */ ListBase chains = {NULL, NULL}; LinkData *chain, *nchain; EditBone *ebo; armature_tag_select_mirrored(arm); /* get chains (ends on chains) */ chains_find_tips(arm->edbo, &chains); if (BLI_listbase_is_empty(&chains)) return OPERATOR_CANCELLED; /* each 'chain' is the last bone in the chain (with no children) */ for (chain = chains.first; chain; chain = nchain) { EditBone *bstart = NULL, *bend = NULL; EditBone *bchild = NULL, *child = NULL; /* temporarily remove chain from list of chains */ nchain = chain->next; BLI_remlink(&chains, chain); /* only consider bones that are visible and selected */ for (ebo = chain->data; ebo; child = ebo, ebo = ebo->parent) { /* check if visible + selected */ if (EBONE_VISIBLE(arm, ebo) && ((ebo->flag & BONE_CONNECTED) || (ebo->parent == NULL)) && (ebo->flag & BONE_SELECTED) ) { /* set either end or start (end gets priority, unless it is already set) */ if (bend == NULL) { bend = ebo; bchild = child; } else bstart = ebo; } else { /* chain is broken... merge any continuous segments then clear */ if (bstart && bend) bones_merge(obedit, bstart, bend, bchild, &chains); bstart = NULL; bend = NULL; bchild = NULL; } } /* merge from bstart to bend if something not merged */ if (bstart && bend) bones_merge(obedit, bstart, bend, bchild, &chains); /* put back link */ BLI_insertlinkbefore(&chains, nchain, chain); } armature_tag_unselect(arm); BLI_freelistN(&chains); } /* updates */ ED_armature_edit_sync_selection(arm->edbo); WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit); return OPERATOR_FINISHED; }
static int armature_calc_roll_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_edit_object(C); eCalcRollTypes type = RNA_enum_get(op->ptr, "type"); const bool axis_only = RNA_boolean_get(op->ptr, "axis_only"); /* axis_flip when matching the active bone never makes sense */ bool axis_flip = ((type >= CALC_ROLL_ACTIVE) ? RNA_boolean_get(op->ptr, "axis_flip") : (type >= CALC_ROLL_TAN_NEG_X) ? true : false); float imat[3][3]; bArmature *arm = ob->data; EditBone *ebone; if ((type >= CALC_ROLL_NEG_X) && (type <= CALC_ROLL_TAN_NEG_Z)) { type -= (CALC_ROLL_ACTIVE - CALC_ROLL_NEG_X); axis_flip = true; } copy_m3_m4(imat, ob->obmat); invert_m3(imat); if (type == CALC_ROLL_CURSOR) { /* Cursor */ Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); /* can be NULL */ float cursor_local[3]; const float *cursor = ED_view3d_cursor3d_get(scene, v3d); invert_m4_m4(ob->imat, ob->obmat); copy_v3_v3(cursor_local, cursor); mul_m4_v3(ob->imat, cursor_local); /* cursor */ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) { float cursor_rel[3]; sub_v3_v3v3(cursor_rel, cursor_local, ebone->head); if (axis_flip) negate_v3(cursor_rel); if (normalize_v3(cursor_rel) != 0.0f) { ebone->roll = ED_armature_ebone_roll_to_vector(ebone, cursor_rel, axis_only); } } } } else if (ELEM(type, CALC_ROLL_TAN_POS_X, CALC_ROLL_TAN_POS_Z)) { for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { if (ebone->parent) { bool is_edit = (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)); bool is_edit_parent = (EBONE_VISIBLE(arm, ebone->parent) && EBONE_EDITABLE(ebone->parent)); if (is_edit || is_edit_parent) { EditBone *ebone_other = ebone->parent; float dir_a[3]; float dir_b[3]; float vec[3]; bool is_vec_zero; sub_v3_v3v3(dir_a, ebone->tail, ebone->head); normalize_v3(dir_a); /* find the first bone in the chane with a different direction */ do { sub_v3_v3v3(dir_b, ebone_other->head, ebone_other->tail); normalize_v3(dir_b); if (type == CALC_ROLL_TAN_POS_Z) { cross_v3_v3v3(vec, dir_a, dir_b); } else { add_v3_v3v3(vec, dir_a, dir_b); } } while ((is_vec_zero = (normalize_v3(vec) < 0.00001f)) && (ebone_other = ebone_other->parent)); if (!is_vec_zero) { if (axis_flip) negate_v3(vec); if (is_edit) { ebone->roll = ED_armature_ebone_roll_to_vector(ebone, vec, axis_only); } /* parentless bones use cross product with child */ if (is_edit_parent) { if (ebone->parent->parent == NULL) { ebone->parent->roll = ED_armature_ebone_roll_to_vector(ebone->parent, vec, axis_only); } } } } } } } else { float vec[3] = {0.0f, 0.0f, 0.0f}; if (type == CALC_ROLL_VIEW) { /* View */ RegionView3D *rv3d = CTX_wm_region_view3d(C); if (rv3d == NULL) { BKE_report(op->reports, RPT_ERROR, "No region view3d available"); return OPERATOR_CANCELLED; } copy_v3_v3(vec, rv3d->viewinv[2]); mul_m3_v3(imat, vec); } else if (type == CALC_ROLL_ACTIVE) { float mat[3][3]; ebone = (EditBone *)arm->act_edbone; if (ebone == NULL) { BKE_report(op->reports, RPT_ERROR, "No active bone set"); return OPERATOR_CANCELLED; } ED_armature_ebone_to_mat3(ebone, mat); copy_v3_v3(vec, mat[2]); } else { /* Axis */ assert(type <= 5); if (type < 3) vec[type] = 1.0f; else vec[type - 2] = -1.0f; mul_m3_v3(imat, vec); normalize_v3(vec); } if (axis_flip) negate_v3(vec); for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) { /* roll func is a callback which assumes that all is well */ ebone->roll = ED_armature_ebone_roll_to_vector(ebone, vec, axis_only); } } } if (arm->flag & ARM_MIRROR_EDIT) { for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { if ((EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) == 0) { EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, ebone); if (ebone_mirr && (EBONE_VISIBLE(arm, ebone_mirr) && EBONE_EDITABLE(ebone_mirr))) { ebone->roll = -ebone_mirr->roll; } } } } /* note, notifier might evolve */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); return OPERATOR_FINISHED; }
static int armature_align_bones_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_edit_object(C); bArmature *arm = (bArmature *)ob->data; EditBone *actbone = CTX_data_active_bone(C); EditBone *actmirb = NULL; int num_selected_bones; /* there must be an active bone */ if (actbone == NULL) { BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone"); return OPERATOR_CANCELLED; } else if (arm->flag & ARM_MIRROR_EDIT) { /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone * (i.e. selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R"). * This is useful for arm-chains, for example parenting lower arm to upper arm * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent") * then just use actbone. Useful when doing upper arm to spine. */ actmirb = ED_armature_ebone_get_mirrored(arm->edbo, actbone); if (actmirb == NULL) actmirb = actbone; } /* if there is only 1 selected bone, we assume that that is the active bone, * since a user will need to have clicked on a bone (thus selecting it) to make it active */ num_selected_bones = CTX_DATA_COUNT(C, selected_editable_bones); if (num_selected_bones <= 1) { /* When only the active bone is selected, and it has a parent, * align it to the parent, as that is the only possible outcome. */ if (actbone->parent) { bone_align_to_bone(arm->edbo, actbone, actbone->parent); if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent)) bone_align_to_bone(arm->edbo, actmirb, actmirb->parent); BKE_reportf(op->reports, RPT_INFO, "Aligned bone '%s' to parent", actbone->name); } } else { /* Align 'selected' bones to the active one * - the context iterator contains both selected bones and their mirrored copies, * so we assume that unselected bones are mirrored copies of some selected bone * - since the active one (and/or its mirror) will also be selected, we also need * to check that we are not trying to operate on them, since such an operation * would cause errors */ /* align selected bones to the active one */ CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) { if (ELEM(ebone, actbone, actmirb) == 0) { if (ebone->flag & BONE_SELECTED) bone_align_to_bone(arm->edbo, ebone, actbone); else bone_align_to_bone(arm->edbo, ebone, actmirb); } } CTX_DATA_END; BKE_reportf(op->reports, RPT_INFO, "%d bones aligned to bone '%s'", num_selected_bones, actbone->name); } /* note, notifier might evolve */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); return OPERATOR_FINISHED; }
int bwlabel(IplImage* img, int n, int* labels) { if(n != 4 && n != 8) n = 4; int nr = img->height; int nc = img->width; int total = nr * nc; // results memset(labels, 0, total * sizeof(int)); int nobj = 0; // number of objects found in image // other variables int* lset = new int[total]; // label table memset(lset, 0, total * sizeof(int)); int ntable = 0; for( int r = 0; r < nr; r++ ) { for( int c = 0; c < nc; c++ ) { if ( ELEM(img, r, c) ) // if A is an object { // get the neighboring pixels B, C, D, and E int B, C, D, E; if ( c == 0 ) B = 0; else B = find( lset, ONETWO(labels, r, c - 1, nc) ); if ( r == 0 ) C = 0; else C = find( lset, ONETWO(labels, r - 1, c, nc) ); if ( r == 0 || c == 0 ) D = 0; else D = find( lset, ONETWO(labels, r - 1, c - 1, nc) ); if ( r == 0 || c == nc - 1 ) E = 0; else E = find( lset, ONETWO(labels, r - 1, c + 1, nc) ); if ( n == 4 ) { // apply 4 connectedness if ( B && C ) { // B and C are labeled if ( B == C ) ONETWO(labels, r, c, nc) = B; else { lset[C] = B; ONETWO(labels, r, c, nc) = B; } } else if ( B ) // B is object but C is not ONETWO(labels, r, c, nc) = B; else if ( C ) // C is object but B is not ONETWO(labels, r, c, nc) = C; else { // B, C, D not object - new object // label and put into table ntable++; ONETWO(labels, r, c, nc) = lset[ ntable ] = ntable; } } else if ( n == 6 ) { // apply 6 connected ness if ( D ) // D object, copy label and move on ONETWO(labels, r, c, nc) = D; else if ( B && C ) { // B and C are labeled if ( B == C ) ONETWO(labels, r, c, nc) = B; else { int tlabel = MIN(B,C); lset[B] = tlabel; lset[C] = tlabel; ONETWO(labels, r, c, nc) = tlabel; } } else if ( B ) // B is object but C is not ONETWO(labels, r, c, nc) = B; else if ( C ) // C is object but B is not ONETWO(labels, r, c, nc) = C; else { // B, C, D not object - new object // label and put into table ntable++; ONETWO(labels, r, c, nc) = lset[ ntable ] = ntable; } } else if ( n == 8 ) { // apply 8 connectedness if ( B || C || D || E ) { int tlabel = B; if ( B ) tlabel = B; else if ( C ) tlabel = C; else if ( D ) tlabel = D; else if ( E ) tlabel = E; ONETWO(labels, r, c, nc) = tlabel; if ( B && B != tlabel ) lset[B] = tlabel; if ( C && C != tlabel ) lset[C] = tlabel; if ( D && D != tlabel ) lset[D] = tlabel; if ( E && E != tlabel ) lset[E] = tlabel; } else { // label and put into table ntable++; ONETWO(labels, r, c, nc) = lset[ ntable ] = ntable; } } } else { ONETWO(labels, r, c, nc) = NO_OBJECT; // A is not an object so leave it } } } // consolidate component table for( int i = 0; i <= ntable; i++ ) lset[i] = find( lset, i ); // run image through the look-up table for( int r = 0; r < nr; r++ ) for( int c = 0; c < nc; c++ ) ONETWO(labels, r, c, nc) = lset[ ONETWO(labels, r, c, nc) ]; // count up the objects in the image for( int i = 0; i <= ntable; i++ ) lset[i] = 0; for( int r = 0; r < nr; r++ ) for( int c = 0; c < nc; c++ ) lset[ ONETWO(labels, r, c, nc) ]++; // number the objects from 1 through n objects nobj = 0; lset[0] = 0; for( int i = 1; i <= ntable; i++ ) if ( lset[i] > 0 ) lset[i] = ++nobj; // run through the look-up table again for( int r = 0; r < nr; r++ ) for( int c = 0; c < nc; c++ ) ONETWO(labels, r, c, nc) = lset[ ONETWO(labels, r, c, nc) ]; // delete[] lset; return nobj; }
uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int index, const char *name, int icon, int x1, int y1, int x2, int y2) { uiBut *but = NULL; switch (RNA_property_type(prop)) { case PROP_BOOLEAN: { int arraylen = RNA_property_array_length(ptr, prop); if (arraylen && index == -1) return NULL; if (icon && name && name[0] == '\0') but = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); else if (icon) but = uiDefIconTextButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); else but = uiDefButR_prop(block, UI_BTYPE_CHECKBOX, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); break; } case PROP_INT: case PROP_FLOAT: { int arraylen = RNA_property_array_length(ptr, prop); if (arraylen && index == -1) { if (ELEM(RNA_property_subtype(prop), PROP_COLOR, PROP_COLOR_GAMMA)) { but = uiDefButR_prop(block, UI_BTYPE_COLOR, 0, name, x1, y1, x2, y2, ptr, prop, -1, 0, 0, -1, -1, NULL); } else { return NULL; } } else if (RNA_property_subtype(prop) == PROP_PERCENTAGE || RNA_property_subtype(prop) == PROP_FACTOR) but = uiDefButR_prop(block, UI_BTYPE_NUM_SLIDER, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); else but = uiDefButR_prop(block, UI_BTYPE_NUM, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) { UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE); } break; } case PROP_ENUM: if (icon && name && name[0] == '\0') but = uiDefIconButR_prop(block, UI_BTYPE_MENU, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); else if (icon) but = uiDefIconTextButR_prop(block, UI_BTYPE_MENU, 0, icon, NULL, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); else but = uiDefButR_prop(block, UI_BTYPE_MENU, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); break; case PROP_STRING: if (icon && name && name[0] == '\0') but = uiDefIconButR_prop(block, UI_BTYPE_TEXT, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); else if (icon) but = uiDefIconTextButR_prop(block, UI_BTYPE_TEXT, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); else but = uiDefButR_prop(block, UI_BTYPE_TEXT, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); PropertySubType subtype = RNA_property_subtype(prop); if (!(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME) || (block->flag & UI_BLOCK_LIST_ITEM))) { UI_but_flag_enable(but, UI_BUT_VALUE_CLEAR); } if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) { UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE); } break; case PROP_POINTER: { PointerRNA pptr; pptr = RNA_property_pointer_get(ptr, prop); if (!pptr.type) pptr.type = RNA_property_pointer_type(ptr, prop); icon = RNA_struct_ui_icon(pptr.type); if (icon == ICON_DOT) icon = 0; but = uiDefIconTextButR_prop(block, UI_BTYPE_SEARCH_MENU, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); break; } case PROP_COLLECTION: { char text[256]; BLI_snprintf(text, sizeof(text), IFACE_("%d items"), RNA_property_collection_length(ptr, prop)); but = uiDefBut(block, UI_BTYPE_LABEL, 0, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, NULL); UI_but_flag_enable(but, UI_BUT_DISABLED); break; } default: but = NULL; break; } return but; }
bp_Table * bp_parseTable(bp_Context * context, xmlNodePtr node) { bp_Table * result = malloc(sizeof(bp_Table)); bp_Node * const parent = &result->node; xmlAttrPtr attr; xmlNodePtr child, grand; bp_pushBlockBorder(context); bp_pushBlockInside(context); bp_pushInline(context); bp_initNode(&result->node, BPE_TABLE); result->_float = bp_defaultFloatAttributes; result->blockOutside = *(context->blockOutside); result->caption = NULL; result->nCols = 0; result->nRows = 0; for (attr = node->properties; attr; attr = attr->next) { bp_parseFloatAttribute(context, &result->_float, attr); bp_parseBlockOutsideAttribute(context, &result->blockOutside, attr); bp_parseBlockBorderAttribute(context, context->blockBorder, attr); bp_parseBlockInsideAttribute(context, context->blockInside, attr); bp_parseInlineAttribute(context, context->inlineAttr, attr); } result->blockBorder = *(context->blockBorder); // shared with children for (child = node->children; child; child = child->next) { switch(ELEM(child)) { case BPE_TR: result->nRows++; break; case BPE_TC: result->nCols++; break; case BPE_CAPTION: result->caption = bp_parseCaption(context, child); default: DISCARD(child); } } if (result->nRows) { int * colHeights = NULL; int col, row = 0; result->nCols = 0; for (child = node->children; child; child = child->next) { if(ELEM(child) == BPE_TR) { bp_pushBlockBorder(context); bp_pushBlockInside(context); bp_pushInline(context); for (attr = child->properties; attr; attr = attr->next) { bp_parseBlockBorderAttribute(context, context->blockBorder, attr); bp_parseBlockInsideAttribute(context, context->blockInside, attr); bp_parseInlineAttribute(context, context->inlineAttr, attr); } col = 0; for (grand = child->children; grand; grand = grand->next) { while ((col < result->nCols) && (colHeights[col] >= row)) col++; if(ELEM(grand) == BPE_TD) { bp_Cell * cell = bp_parseCell(context, grand, row, col); ADD(cell); if (cell->endCol >= result->nCols) { result->nCols = cell->endCol + 1; colHeights = realloc(colHeights, result->nCols * sizeof(int)); } for (col=cell->startCol; col <= cell->endCol; col++) { colHeights[col] = cell->endRow; } } else { DISCARD(grand); } } bp_popBlockBorder(context); bp_popBlockInside(context); bp_popInline(context); row++; } } if(colHeights) free(colHeights); } else if (result->nCols) { int * rowWidths = NULL; int col = 0, row; result->nRows = 0; for (child = node->children; child; child = child->next) { if(ELEM(child) == BPE_TC) { bp_pushBlockBorder(context); bp_pushBlockInside(context); bp_pushInline(context); for (attr = child->properties; attr; attr = attr->next) { bp_parseBlockBorderAttribute(context, context->blockBorder, attr); bp_parseBlockInsideAttribute(context, context->blockInside, attr); bp_parseInlineAttribute(context, context->inlineAttr, attr); } row = 0; for (grand = child->children; grand; grand = grand->next) { while ((row < result->nRows) && (rowWidths[row] >= col)) row++; if(ELEM(grand) == BPE_TD) { bp_Cell * cell = bp_parseCell(context, grand, row, col); ADD(cell); if (cell->endRow >= result->nRows) { result->nRows = cell->endRow + 1; rowWidths = realloc(rowWidths, result->nRows * sizeof(int)); } for (row=cell->startRow; row <= cell->endRow; row++) { rowWidths[row] = cell->endCol; } } else { DISCARD(grand); } } bp_popBlockBorder(context); bp_popBlockInside(context); bp_popInline(context); col++; } } if(rowWidths) free(rowWidths); } bp_popBlockBorder(context); bp_popBlockInside(context); bp_popInline(context); return result; }
static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], ParticleSystem *psys, int level, int animated) { GroupObject *go; Object *ob=NULL, **oblist=NULL, obcopy, *obcopylist=NULL; DupliObject *dob; ParticleDupliWeight *dw; ParticleSettings *part; ParticleData *pa; ChildParticle *cpa=NULL; ParticleKey state; ParticleCacheKey *cache; float ctime, pa_time, scale = 1.0f; float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size=0.0; float (*obmat)[4], (*oldobmat)[4]; int a, b, counter, hair = 0; int totpart, totchild, totgroup=0 /*, pa_num */; int no_draw_flag = PARS_UNEXIST; if (psys==NULL) return; /* simple preventing of too deep nested groups */ if (level>MAX_DUPLI_RECUR) return; part=psys->part; if (part==NULL) return; if (!psys_check_enabled(par, psys)) return; if (G.rendering == 0) no_draw_flag |= PARS_NO_DISP; ctime = BKE_curframe(scene); /* NOTE: in old animsys, used parent object's timeoffset... */ totpart = psys->totpart; totchild = psys->totchild; BLI_srandom(31415926 + psys->seed); if ((psys->renderdata || part->draw_as==PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) { ParticleSimulationData sim= {NULL}; sim.scene= scene; sim.ob= par; sim.psys= psys; sim.psmd= psys_get_modifier(par, psys); /* make sure emitter imat is in global coordinates instead of render view coordinates */ invert_m4_m4(par->imat, par->obmat); /* first check for loops (particle system object used as dupli object) */ if (part->ren_as == PART_DRAW_OB) { if (ELEM(part->dup_ob, NULL, par)) return; } else { /*PART_DRAW_GR */ if (part->dup_group == NULL || part->dup_group->gobject.first == NULL) return; for (go=part->dup_group->gobject.first; go; go=go->next) if (go->ob == par) return; } /* if we have a hair particle system, use the path cache */ if (part->type == PART_HAIR) { if (psys->flag & PSYS_HAIR_DONE) hair= (totchild == 0 || psys->childcache) && psys->pathcache; if (!hair) return; /* we use cache, update totchild according to cached data */ totchild = psys->totchildcache; totpart = psys->totcached; } psys_check_group_weights(part); psys->lattice = psys_get_lattice(&sim); /* gather list of objects or single object */ if (part->ren_as==PART_DRAW_GR) { group_handle_recalc_and_update(scene, par, part->dup_group); if (part->draw & PART_DRAW_COUNT_GR) { for (dw=part->dupliweights.first; dw; dw=dw->next) totgroup += dw->count; } else { for (go=part->dup_group->gobject.first; go; go=go->next) totgroup++; } /* we also copy the actual objects to restore afterwards, since * where_is_object_time will change the object which breaks transform */ oblist = MEM_callocN(totgroup*sizeof(Object *), "dupgroup object list"); obcopylist = MEM_callocN(totgroup*sizeof(Object), "dupgroup copy list"); if (part->draw & PART_DRAW_COUNT_GR && totgroup) { dw = part->dupliweights.first; for (a=0; a<totgroup; dw=dw->next) { for (b=0; b<dw->count; b++, a++) { oblist[a] = dw->ob; obcopylist[a] = *dw->ob; } } } else { go = part->dup_group->gobject.first; for (a=0; a<totgroup; a++, go=go->next) { oblist[a] = go->ob; obcopylist[a] = *go->ob; } } } else { ob = part->dup_ob; obcopy = *ob; } if (totchild==0 || part->draw & PART_DRAW_PARENT) a = 0; else a = totpart; for (pa=psys->particles,counter=0; a<totpart+totchild; a++,pa++,counter++) { if (a<totpart) { /* handle parent particle */ if (pa->flag & no_draw_flag) continue; /* pa_num = pa->num; */ /* UNUSED */ pa_time = pa->time; size = pa->size; } else { /* handle child particle */ cpa = &psys->child[a - totpart]; /* pa_num = a; */ /* UNUSED */ pa_time = psys->particles[cpa->parent].time; size = psys_get_child_size(psys, cpa, ctime, NULL); } /* some hair paths might be non-existent so they can't be used for duplication */ if (hair && ((a < totpart && psys->pathcache[a]->steps < 0) || (a >= totpart && psys->childcache[a-totpart]->steps < 0))) continue; if (part->ren_as==PART_DRAW_GR) { /* prevent divide by zero below [#28336] */ if (totgroup == 0) continue; /* for groups, pick the object based on settings */ if (part->draw&PART_DRAW_RAND_GR) b= BLI_rand() % totgroup; else b= a % totgroup; ob = oblist[b]; obmat = oblist[b]->obmat; oldobmat = obcopylist[b].obmat; } else { obmat= ob->obmat; oldobmat= obcopy.obmat; } if (hair) { /* hair we handle separate and compute transform based on hair keys */ if (a < totpart) { cache = psys->pathcache[a]; psys_get_dupli_path_transform(&sim, pa, NULL, cache, pamat, &scale); } else { cache = psys->childcache[a-totpart]; psys_get_dupli_path_transform(&sim, NULL, cpa, cache, pamat, &scale); } copy_v3_v3(pamat[3], cache->co); pamat[3][3]= 1.0f; } else { /* first key */ state.time = ctime; if (psys_get_particle_state(&sim, a, &state, 0) == 0) { continue; } else { float tquat[4]; normalize_qt_qt(tquat, state.rot); quat_to_mat4(pamat, tquat); copy_v3_v3(pamat[3], state.co); pamat[3][3]= 1.0f; } } if (part->ren_as==PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) { for (go= part->dup_group->gobject.first, b=0; go; go= go->next, b++) { copy_m4_m4(tmat, oblist[b]->obmat); /* apply particle scale */ mul_mat3_m4_fl(tmat, size*scale); mul_v3_fl(tmat[3], size*scale); /* group dupli offset, should apply after everything else */ if (!is_zero_v3(part->dup_group->dupli_ofs)) sub_v3_v3v3(tmat[3], tmat[3], part->dup_group->dupli_ofs); /* individual particle transform */ mult_m4_m4m4(tmat, pamat, tmat); if (par_space_mat) mult_m4_m4m4(mat, par_space_mat, tmat); else copy_m4_m4(mat, tmat); dob= new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS, animated); copy_m4_m4(dob->omat, obcopylist[b].obmat); if (G.rendering) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } else { /* to give ipos in object correct offset */ where_is_object_time(scene, ob, ctime-pa_time); copy_v3_v3(vec, obmat[3]); obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f; /* particle rotation uses x-axis as the aligned axis, so pre-rotate the object accordingly */ if ((part->draw & PART_DRAW_ROTATE_OB) == 0) { float xvec[3], q[4]; xvec[0] = -1.f; xvec[1] = xvec[2] = 0; vec_to_quat(q, xvec, ob->trackflag, ob->upflag); quat_to_mat4(obmat, q); obmat[3][3]= 1.0f; } /* Normal particles and cached hair live in global space so we need to * remove the real emitter's transformation before 2nd order duplication. */ if (par_space_mat && GS(id->name) != ID_GR) mult_m4_m4m4(mat, psys->imat, pamat); else copy_m4_m4(mat, pamat); mult_m4_m4m4(tmat, mat, obmat); mul_mat3_m4_fl(tmat, size*scale); if (par_space_mat) mult_m4_m4m4(mat, par_space_mat, tmat); else copy_m4_m4(mat, tmat); if (part->draw & PART_DRAW_GLOBAL_OB) add_v3_v3v3(mat[3], mat[3], vec); dob= new_dupli_object(lb, ob, mat, ob->lay, counter, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, animated); copy_m4_m4(dob->omat, oldobmat); if (G.rendering) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } /* restore objects since they were changed in where_is_object_time */ if (part->ren_as==PART_DRAW_GR) { for (a=0; a<totgroup; a++) *(oblist[a])= obcopylist[a]; } else *ob= obcopy; } /* clean up */ if (oblist) MEM_freeN(oblist); if (obcopylist) MEM_freeN(obcopylist); if (psys->lattice) { end_latt_deform(psys->lattice); psys->lattice = NULL; } }
void curve_deform_verts( Scene *scene, Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3], int numVerts, const char *vgroup, short defaxis) { Curve *cu; int a; CurveDeform cd; MDeformVert *dvert = NULL; int defgrp_index = -1; const bool is_neg_axis = (defaxis > 2); if (cuOb->type != OB_CURVE) return; cu = cuOb->data; init_curve_deform(cuOb, target, &cd); /* dummy bounds, keep if CU_DEFORM_BOUNDS_OFF is set */ if (is_neg_axis == false) { cd.dmin[0] = cd.dmin[1] = cd.dmin[2] = 0.0f; cd.dmax[0] = cd.dmax[1] = cd.dmax[2] = 1.0f; } else { /* negative, these bounds give a good rest position */ cd.dmin[0] = cd.dmin[1] = cd.dmin[2] = -1.0f; cd.dmax[0] = cd.dmax[1] = cd.dmax[2] = 0.0f; } /* Check whether to use vertex groups (only possible if target is a Mesh or Lattice). * We want either a Mesh/Lattice with no derived data, or derived data with deformverts. */ if (vgroup && vgroup[0] && ELEM(target->type, OB_MESH, OB_LATTICE)) { defgrp_index = defgroup_name_index(target, vgroup); if (defgrp_index != -1) { /* if there's derived data without deformverts, don't use vgroups */ if (dm) { dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); } else if (target->type == OB_LATTICE) { dvert = ((Lattice *)target->data)->dvert; } else { dvert = ((Mesh *)target->data)->dvert; } } } if (dvert) { MDeformVert *dvert_iter; float vec[3]; if (cu->flag & CU_DEFORM_BOUNDS_OFF) { for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) { const float weight = defvert_find_weight(dvert_iter, defgrp_index); if (weight > 0.0f) { mul_m4_v3(cd.curvespace, vertexCos[a]); copy_v3_v3(vec, vertexCos[a]); calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL); interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight); mul_m4_v3(cd.objectspace, vertexCos[a]); } } } else { /* set mesh min/max bounds */ INIT_MINMAX(cd.dmin, cd.dmax); for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) { if (defvert_find_weight(dvert_iter, defgrp_index) > 0.0f) { mul_m4_v3(cd.curvespace, vertexCos[a]); minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]); } } for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) { const float weight = defvert_find_weight(dvert_iter, defgrp_index); if (weight > 0.0f) { /* already in 'cd.curvespace', prev for loop */ copy_v3_v3(vec, vertexCos[a]); calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL); interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight); mul_m4_v3(cd.objectspace, vertexCos[a]); } } } } else { if (cu->flag & CU_DEFORM_BOUNDS_OFF) { for (a = 0; a < numVerts; a++) { mul_m4_v3(cd.curvespace, vertexCos[a]); calc_curve_deform(scene, cuOb, vertexCos[a], defaxis, &cd, NULL); mul_m4_v3(cd.objectspace, vertexCos[a]); } } else { /* set mesh min max bounds */ INIT_MINMAX(cd.dmin, cd.dmax); for (a = 0; a < numVerts; a++) { mul_m4_v3(cd.curvespace, vertexCos[a]); minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]); } for (a = 0; a < numVerts; a++) { /* already in 'cd.curvespace', prev for loop */ calc_curve_deform(scene, cuOb, vertexCos[a], defaxis, &cd, NULL); mul_m4_v3(cd.objectspace, vertexCos[a]); } } } }
static char *rna_ColorRamp_path(PointerRNA *ptr) { char *path = NULL; /* handle the cases where a single data-block may have 2 ramp types */ if (ptr->id.data) { ID *id = ptr->id.data; switch (GS(id->name)) { case ID_MA: /* material has 2 cases - diffuse and specular */ { Material *ma = (Material *)id; if (ptr->data == ma->ramp_col) path = BLI_strdup("diffuse_ramp"); else if (ptr->data == ma->ramp_spec) path = BLI_strdup("specular_ramp"); break; } case ID_NT: { bNodeTree *ntree = (bNodeTree *)id; bNode *node; PointerRNA node_ptr; char *node_path; for (node = ntree->nodes.first; node; node = node->next) { if (ELEM(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) { if (node->storage == ptr->data) { /* all node color ramp properties called 'color_ramp' * prepend path from ID to the node */ RNA_pointer_create(id, &RNA_Node, node, &node_ptr); node_path = RNA_path_from_ID_to_struct(&node_ptr); path = BLI_sprintfN("%s.color_ramp", node_path); MEM_freeN(node_path); } } } break; } case ID_LS: { char *path = BKE_linestyle_path_to_color_ramp((FreestyleLineStyle *)id, (ColorBand *)ptr->data); if (path) return path; break; } default: /* everything else just uses 'color_ramp' */ path = BLI_strdup("color_ramp"); break; } } else { /* everything else just uses 'color_ramp' */ path = BLI_strdup("color_ramp"); } return path; }
static void vol_shade_one_lamp(struct ShadeInput *shi, float *co, LampRen *lar, float *lacol) { float visifac, lv[3], lampdist; float tr[3]={1.0,1.0,1.0}; float hitco[3], *atten_co; float p, ref_col[3]; if (lar->mode & LA_LAYER) if((lar->lay & shi->obi->lay)==0) return; if ((lar->lay & shi->lay)==0) return; if (lar->energy == 0.0f) return; if ((visifac= lamp_get_visibility(lar, co, lv, &lampdist)) == 0.f) return; copy_v3_v3(lacol, &lar->r); if(lar->mode & LA_TEXTURE) { shi->osatex= 0; do_lamp_tex(lar, lv, shi, lacol, LA_TEXTURE); } mul_v3_fl(lacol, visifac); if (ELEM(lar->type, LA_SUN, LA_HEMI)) VECCOPY(lv, lar->vec); negate_v3(lv); if (shi->mat->vol.shade_type == MA_VOL_SHADE_SHADOWED) { mul_v3_fl(lacol, vol_get_shadow(shi, lar, co)); } else if (ELEM3(shi->mat->vol.shade_type, MA_VOL_SHADE_SHADED, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE)) { Isect is; if (shi->mat->vol.shadeflag & MA_VOL_RECV_EXT_SHADOW) { mul_v3_fl(lacol, vol_get_shadow(shi, lar, co)); if (luminance(lacol) < 0.001f) return; } /* find minimum of volume bounds, or lamp coord */ if (vol_get_bounds(shi, co, lv, hitco, &is, VOL_BOUNDS_SS)) { float dist = len_v3v3(co, hitco); VlakRen *vlr = (VlakRen *)is.hit.face; /* simple internal shadowing */ if (vlr->mat->material_type == MA_TYPE_SURFACE) { lacol[0] = lacol[1] = lacol[2] = 0.0f; return; } if (ELEM(lar->type, LA_SUN, LA_HEMI)) /* infinite lights, can never be inside volume */ atten_co = hitco; else if ( lampdist < dist ) { atten_co = lar->co; } else atten_co = hitco; vol_get_transmittance(shi, tr, co, atten_co); mul_v3_v3v3(lacol, lacol, tr); } else { /* Point is on the outside edge of the volume, * therefore no attenuation, full transmission. * Radiance from lamp remains unchanged */ } } if (luminance(lacol) < 0.001f) return; normalize_v3(lv); p = vol_get_phasefunc(shi, shi->mat->vol.asymmetry, shi->view, lv); /* physically based scattering with non-physically based RGB gain */ vol_get_reflection_color(shi, ref_col, co); lacol[0] *= p * ref_col[0]; lacol[1] *= p * ref_col[1]; lacol[2] *= p * ref_col[2]; }
static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys) { ParticleData *pa=NULL; float min[3], max[3], delta[3], d; MVert *mv, *mvert = dm->getVertDataArray(dm,0); int totvert=dm->getNumVerts(dm), from=psys->part->from; int i, j, k, p, res=psys->part->grid_res, size[3], axis; /* find bounding box of dm */ if (totvert > 0) { mv=mvert; copy_v3_v3(min, mv->co); copy_v3_v3(max, mv->co); mv++; for (i = 1; i < totvert; i++, mv++) { minmax_v3v3_v3(min, max, mv->co); } } else { zero_v3(min); zero_v3(max); } sub_v3_v3v3(delta, max, min); /* determine major axis */ axis = axis_dominant_v3_single(delta); d = delta[axis]/(float)res; size[axis] = res; size[(axis+1)%3] = (int)ceil(delta[(axis+1)%3]/d); size[(axis+2)%3] = (int)ceil(delta[(axis+2)%3]/d); /* float errors grrr.. */ size[(axis+1)%3] = MIN2(size[(axis+1)%3],res); size[(axis+2)%3] = MIN2(size[(axis+2)%3],res); size[0] = MAX2(size[0], 1); size[1] = MAX2(size[1], 1); size[2] = MAX2(size[2], 1); /* no full offset for flat/thin objects */ min[0]+= d < delta[0] ? d/2.f : delta[0]/2.f; min[1]+= d < delta[1] ? d/2.f : delta[1]/2.f; min[2]+= d < delta[2] ? d/2.f : delta[2]/2.f; for (i=0,p=0,pa=psys->particles; i<res; i++) { for (j=0; j<res; j++) { for (k=0; k<res; k++,p++,pa++) { pa->fuv[0] = min[0] + (float)i*d; pa->fuv[1] = min[1] + (float)j*d; pa->fuv[2] = min[2] + (float)k*d; pa->flag |= PARS_UNEXIST; pa->hair_index = 0; /* abused in volume calculation */ } } } /* enable particles near verts/edges/faces/inside surface */ if (from==PART_FROM_VERT) { float vec[3]; pa=psys->particles; min[0] -= d/2.0f; min[1] -= d/2.0f; min[2] -= d/2.0f; for (i=0,mv=mvert; i<totvert; i++,mv++) { sub_v3_v3v3(vec,mv->co,min); vec[0]/=delta[0]; vec[1]/=delta[1]; vec[2]/=delta[2]; pa[((int)(vec[0] * (size[0] - 1)) * res + (int)(vec[1] * (size[1] - 1))) * res + (int)(vec[2] * (size[2] - 1))].flag &= ~PARS_UNEXIST; } } else if (ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) { float co1[3], co2[3]; MFace *mface= NULL, *mface_array; float v1[3], v2[3], v3[3], v4[4], lambda; int a, a1, a2, a0mul, a1mul, a2mul, totface; int amax= from==PART_FROM_FACE ? 3 : 1; totface=dm->getNumTessFaces(dm); mface=mface_array=dm->getTessFaceDataArray(dm,CD_MFACE); for (a=0; a<amax; a++) { if (a==0) { a0mul=res*res; a1mul=res; a2mul=1; } else if (a==1) { a0mul=res; a1mul=1; a2mul=res*res; } else { a0mul=1; a1mul=res*res; a2mul=res; } for (a1=0; a1<size[(a+1)%3]; a1++) { for (a2=0; a2<size[(a+2)%3]; a2++) { mface= mface_array; pa = psys->particles + a1*a1mul + a2*a2mul; copy_v3_v3(co1, pa->fuv); co1[a] -= d < delta[a] ? d/2.f : delta[a]/2.f; copy_v3_v3(co2, co1); co2[a] += delta[a] + 0.001f*d; co1[a] -= 0.001f*d; /* lets intersect the faces */ for (i=0; i<totface; i++,mface++) { copy_v3_v3(v1, mvert[mface->v1].co); copy_v3_v3(v2, mvert[mface->v2].co); copy_v3_v3(v3, mvert[mface->v3].co); bool intersects_tri = isect_axial_line_segment_tri_v3(a, co1, co2, v2, v3, v1, &lambda); if (intersects_tri) { if (from==PART_FROM_FACE) (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST; else /* store number of intersections */ (pa+(int)(lambda*size[a])*a0mul)->hair_index++; } if (mface->v4 && (!intersects_tri || from==PART_FROM_VOLUME)) { copy_v3_v3(v4, mvert[mface->v4].co); if (isect_axial_line_segment_tri_v3(a, co1, co2, v4, v1, v3, &lambda)) { if (from==PART_FROM_FACE) (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST; else (pa+(int)(lambda*size[a])*a0mul)->hair_index++; } } } if (from==PART_FROM_VOLUME) { int in=pa->hair_index%2; if (in) pa->hair_index++; for (i=0; i<size[0]; i++) { if (in || (pa+i*a0mul)->hair_index%2) (pa+i*a0mul)->flag &= ~PARS_UNEXIST; /* odd intersections == in->out / out->in */ /* even intersections -> in stays same */ in=(in + (pa+i*a0mul)->hair_index) % 2; } } } } } } if (psys->part->flag & PART_GRID_HEXAGONAL) { for (i=0,p=0,pa=psys->particles; i<res; i++) { for (j=0; j<res; j++) { for (k=0; k<res; k++,p++,pa++) { if (j%2) pa->fuv[0] += d/2.f; if (k%2) { pa->fuv[0] += d/2.f; pa->fuv[1] += d/2.f; } } } } } if (psys->part->flag & PART_GRID_INVERT) { for (i=0; i<size[0]; i++) { for (j=0; j<size[1]; j++) { pa=psys->particles + res*(i*res + j); for (k=0; k<size[2]; k++, pa++) { pa->flag ^= PARS_UNEXIST; } } } } if (psys->part->grid_rand > 0.f) { float rfac = d * psys->part->grid_rand; for (p=0,pa=psys->particles; p<psys->totpart; p++,pa++) { if (pa->flag & PARS_UNEXIST) continue; pa->fuv[0] += rfac * (psys_frand(psys, p + 31) - 0.5f); pa->fuv[1] += rfac * (psys_frand(psys, p + 32) - 0.5f); pa->fuv[2] += rfac * (psys_frand(psys, p + 33) - 0.5f); } } }
static float fcm_cycles_time( FCurve *fcu, FModifier *fcm, float UNUSED(cvalue), float evaltime, void *storage_) { FMod_Cycles *data = (FMod_Cycles *)fcm->data; tFCMED_Cycles *storage = storage_; float prevkey[2], lastkey[2], cycyofs = 0.0f; short side = 0, mode = 0; int cycles = 0; float ofs = 0; /* Initialize storage. */ storage->cycyofs = 0; /* check if modifier is first in stack, otherwise disable ourself... */ /* FIXME... */ if (fcm->prev) { fcm->flag |= FMODIFIER_FLAG_DISABLED; return evaltime; } /* calculate new evaltime due to cyclic interpolation */ if (fcu && fcu->bezt) { BezTriple *prevbezt = fcu->bezt; BezTriple *lastbezt = prevbezt + fcu->totvert - 1; prevkey[0] = prevbezt->vec[1][0]; prevkey[1] = prevbezt->vec[1][1]; lastkey[0] = lastbezt->vec[1][0]; lastkey[1] = lastbezt->vec[1][1]; } else if (fcu && fcu->fpt) { FPoint *prevfpt = fcu->fpt; FPoint *lastfpt = prevfpt + fcu->totvert - 1; prevkey[0] = prevfpt->vec[0]; prevkey[1] = prevfpt->vec[1]; lastkey[0] = lastfpt->vec[0]; lastkey[1] = lastfpt->vec[1]; } else { return evaltime; } /* check if modifier will do anything * 1) if in data range, definitely don't do anything * 2) if before first frame or after last frame, make sure some cycling is in use */ if (evaltime < prevkey[0]) { if (data->before_mode) { side = -1; mode = data->before_mode; cycles = data->before_cycles; ofs = prevkey[0]; } } else if (evaltime > lastkey[0]) { if (data->after_mode) { side = 1; mode = data->after_mode; cycles = data->after_cycles; ofs = lastkey[0]; } } if ((ELEM(0, side, mode))) { return evaltime; } /* find relative place within a cycle */ { float cycdx = 0, cycdy = 0; float cycle = 0, cyct = 0; /* calculate period and amplitude (total height) of a cycle */ cycdx = lastkey[0] - prevkey[0]; cycdy = lastkey[1] - prevkey[1]; /* check if cycle is infinitely small, to be point of being impossible to use */ if (cycdx == 0) { return evaltime; } /* calculate the 'number' of the cycle */ cycle = ((float)side * (evaltime - ofs) / cycdx); /* calculate the time inside the cycle */ cyct = fmod(evaltime - ofs, cycdx); /* check that cyclic is still enabled for the specified time */ if (cycles == 0) { /* catch this case so that we don't exit when we have (cycles = 0) * as this indicates infinite cycles... */ } else if (cycle > cycles) { /* we are too far away from range to evaluate * TODO: but we should still hold last value... */ return evaltime; } /* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle */ if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) { if (side < 0) { cycyofs = (float)floor((evaltime - ofs) / cycdx); } else { cycyofs = (float)ceil((evaltime - ofs) / cycdx); } cycyofs *= cycdy; } /* special case for cycle start/end */ if (cyct == 0.0f) { evaltime = (side == 1 ? lastkey[0] : prevkey[0]); if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)cycle % 2)) { evaltime = (side == 1 ? prevkey[0] : lastkey[0]); } } /* calculate where in the cycle we are (overwrite evaltime to reflect this) */ else if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)(cycle + 1) % 2)) { /* When 'mirror' option is used and cycle number is odd, this cycle is played in reverse * - for 'before' extrapolation, we need to flip in a different way, otherwise values past * then end of the curve get referenced * (result of fmod will be negative, and with different phase). */ if (side < 0) { evaltime = prevkey[0] - cyct; } else { evaltime = lastkey[0] - cyct; } } else { /* the cycle is played normally... */ evaltime = prevkey[0] + cyct; } if (evaltime < prevkey[0]) { evaltime += cycdx; } } /* store temp data if needed */ if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) { storage->cycyofs = cycyofs; } /* return the new frame to evaluate */ return evaltime; }
/* This function adds data to the keyframes copy/paste buffer, freeing existing data first */ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data) { bAnimListElem *ale; Scene *scene = ac->scene; /* clear buffer first */ free_anim_copybuf(); /* assume that each of these is an F-Curve */ for (ale = anim_data->first; ale; ale = ale->next) { FCurve *fcu = (FCurve *)ale->key_data; tAnimCopybufItem *aci; BezTriple *bezt, *nbezt, *newbuf; int i; /* firstly, check if F-Curve has any selected keyframes * - skip if no selected keyframes found (so no need to create unnecessary copy-buffer data) * - this check should also eliminate any problems associated with using sample-data */ if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ANIM_editkeyframes_ok(BEZT_OK_SELECTED), NULL) == 0) continue; /* init copybuf item info */ aci = MEM_callocN(sizeof(tAnimCopybufItem), "AnimCopybufItem"); aci->id = ale->id; aci->id_type = GS(ale->id->name); aci->grp = fcu->grp; aci->rna_path = MEM_dupallocN(fcu->rna_path); aci->array_index = fcu->array_index; /* detect if this is a bone. We do that here rather than during pasting because ID pointers will get invalidated if we undo. * storing the relevant information here helps avoiding crashes if we undo-repaste */ if ((aci->id_type == ID_OB) && (((Object *)aci->id)->type == OB_ARMATURE) && aci->rna_path) { Object *ob = (Object *)aci->id; bPoseChannel *pchan; char *bone_name; bone_name = BLI_str_quoted_substrN(aci->rna_path, "pose.bones["); pchan = BKE_pose_channel_find_name(ob->pose, bone_name); if (pchan) { aci->is_bone = true; } if (bone_name) MEM_freeN(bone_name); } BLI_addtail(&animcopybuf, aci); /* add selected keyframes to buffer */ /* TODO: currently, we resize array every time we add a new vert - * this works ok as long as it is assumed only a few keys are copied */ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { if (BEZT_ISSEL_ANY(bezt)) { /* add to buffer */ newbuf = MEM_callocN(sizeof(BezTriple) * (aci->totvert + 1), "copybuf beztriple"); /* assume that since we are just re-sizing the array, just copy all existing data across */ if (aci->bezt) memcpy(newbuf, aci->bezt, sizeof(BezTriple) * (aci->totvert)); /* copy current beztriple across too */ nbezt = &newbuf[aci->totvert]; *nbezt = *bezt; /* ensure copy buffer is selected so pasted keys are selected */ BEZT_SEL_ALL(nbezt); /* free old array and set the new */ if (aci->bezt) MEM_freeN(aci->bezt); aci->bezt = newbuf; aci->totvert++; /* check if this is the earliest frame encountered so far */ if (bezt->vec[1][0] < animcopy_firstframe) animcopy_firstframe = bezt->vec[1][0]; if (bezt->vec[1][0] > animcopy_lastframe) animcopy_lastframe = bezt->vec[1][0]; } } } /* check if anything ended up in the buffer */ if (ELEM(NULL, animcopybuf.first, animcopybuf.last)) return -1; /* in case 'relative' paste method is used */ animcopy_cfra = CFRA; /* everything went fine */ return 0; }
static void brush_painter_2d_refresh_cache(ImagePaintState *s, BrushPainter *painter, const float pos[2], const float mouse[2], float pressure, float distance, float size) { const Scene *scene = painter->scene; UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; Brush *brush = painter->brush; BrushPainterCache *cache = &painter->cache; const int diameter = 2 * size; bool do_random = false; bool do_partial_update = false; bool update_color = (brush->flag & BRUSH_USE_GRADIENT) && ((ELEM(brush->gradient_stroke_mode, BRUSH_GRADIENT_SPACING_REPEAT, BRUSH_GRADIENT_SPACING_CLAMP)) || (cache->last_pressure != pressure)); float tex_rotation = -brush->mtex.rot; float mask_rotation = -brush->mask_mtex.rot; painter->pool = BKE_image_pool_new(); /* determine how can update based on textures used */ if (painter->cache.is_texbrush) { if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) { tex_rotation += ups->brush_rotation; } else if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM) do_random = true; else if (!((brush->flag & BRUSH_ANCHORED) || update_color)) do_partial_update = true; brush_painter_2d_tex_mapping(s, diameter, painter->startpaintpos, pos, mouse, brush->mtex.brush_map_mode, &painter->tex_mapping); } if (painter->cache.is_maskbrush) { bool renew_maxmask = false; bool do_partial_update_mask = false; /* invalidate case for all mapping modes */ if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) { mask_rotation += ups->brush_rotation_sec; } else if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM) { renew_maxmask = true; } else if (!(brush->flag & BRUSH_ANCHORED)) { do_partial_update_mask = true; renew_maxmask = true; } /* explicilty disable partial update even if it has been enabled above */ if (brush->mask_pressure) { do_partial_update_mask = false; renew_maxmask = true; } if ((diameter != cache->lastdiameter) || (mask_rotation != cache->last_mask_rotation) || renew_maxmask) { if (cache->tex_mask) { MEM_freeN(cache->tex_mask); cache->tex_mask = NULL; } brush_painter_2d_tex_mapping(s, diameter, painter->startpaintpos, pos, mouse, brush->mask_mtex.brush_map_mode, &painter->mask_mapping); if (do_partial_update_mask) brush_painter_mask_imbuf_partial_update(painter, pos, diameter); else cache->tex_mask = brush_painter_mask_ibuf_new(painter, diameter); cache->last_mask_rotation = mask_rotation; } } /* curve mask can only change if the size changes */ if (diameter != cache->lastdiameter) { if (cache->curve_mask) { MEM_freeN(cache->curve_mask); cache->curve_mask = NULL; } cache->curve_mask = brush_painter_curve_mask_new(painter, diameter, size); } /* detect if we need to recreate image brush buffer */ if ((diameter != cache->lastdiameter) || (tex_rotation != cache->last_tex_rotation) || do_random || update_color) { if (cache->ibuf) { IMB_freeImBuf(cache->ibuf); cache->ibuf = NULL; } if (do_partial_update) { /* do partial update of texture */ brush_painter_imbuf_partial_update(painter, pos, diameter); } else { /* create brush from scratch */ cache->ibuf = brush_painter_imbuf_new(painter, diameter, pressure, distance); } cache->lastdiameter = diameter; cache->last_tex_rotation = tex_rotation; cache->last_pressure = pressure; } else if (do_partial_update) { /* do only partial update of texture */ int dx = (int)painter->lastpaintpos[0] - (int)pos[0]; int dy = (int)painter->lastpaintpos[1] - (int)pos[1]; if ((dx != 0) || (dy != 0)) { brush_painter_imbuf_partial_update(painter, pos, diameter); } } BKE_image_pool_free(painter->pool); painter->pool = NULL; }
static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_mode, bool column, bool same_channel) { ListBase anim_data = {NULL, NULL}; DLRBT_Tree anim_keys; bAnimListElem *ale; int filter; View2D *v2d = &ac->ar->v2d; bDopeSheet *ads = NULL; int channel_index; bool found = false; float frame = 0.0f; /* frame of keyframe under mouse - NLA corrections not applied/included */ float selx = 0.0f; /* frame of keyframe under mouse */ float key_hsize; float x, y; rctf rectf; /* get dopesheet info */ if (ac->datatype == ANIMCONT_DOPESHEET) ads = ac->data; /* use View2D to determine the index of the channel (i.e a row in the list) where keyframe was */ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); UI_view2d_listview_view_to_cell(v2d, 0, ACHANNEL_STEP(ac), 0, (float)ACHANNEL_HEIGHT_HALF(ac), x, y, NULL, &channel_index); /* x-range to check is +/- 7px for standard keyframe under standard dpi/y-scale (in screen/region-space), * on either side of mouse click (size of keyframe icon) */ key_hsize = ACHANNEL_HEIGHT(ac) * 0.8f; /* standard channel height (to allow for some slop) */ key_hsize = roundf(key_hsize / 2.0f); /* half-size (for either side), but rounded up to nearest int (for easier targeting) */ UI_view2d_region_to_view(v2d, mval[0] - (int)key_hsize, mval[1], &rectf.xmin, &rectf.ymin); UI_view2d_region_to_view(v2d, mval[0] + (int)key_hsize, mval[1], &rectf.xmax, &rectf.ymax); /* filter data */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* try to get channel */ ale = BLI_findlink(&anim_data, channel_index); if (ale == NULL) { /* channel not found */ printf("Error: animation channel (index = %d) not found in mouse_action_keys()\n", channel_index); ANIM_animdata_freelist(&anim_data); return; } else { /* found match - must return here... */ AnimData *adt = ANIM_nla_mapping_get(ac, ale); ActKeyColumn *ak, *akn = NULL; /* make list of keyframes */ BLI_dlrbTree_init(&anim_keys); if (ale->key_data) { switch (ale->datatype) { case ALE_SCE: { Scene *scene = (Scene *)ale->key_data; scene_to_keylist(ads, scene, &anim_keys, NULL); break; } case ALE_OB: { Object *ob = (Object *)ale->key_data; ob_to_keylist(ads, ob, &anim_keys, NULL); break; } case ALE_ACT: { bAction *act = (bAction *)ale->key_data; action_to_keylist(adt, act, &anim_keys, NULL); break; } case ALE_FCURVE: { FCurve *fcu = (FCurve *)ale->key_data; fcurve_to_keylist(adt, fcu, &anim_keys, NULL); break; } } } else if (ale->type == ANIMTYPE_SUMMARY) { /* dopesheet summary covers everything */ summary_to_keylist(ac, &anim_keys, NULL); } else if (ale->type == ANIMTYPE_GROUP) { // TODO: why don't we just give groups key_data too? bActionGroup *agrp = (bActionGroup *)ale->data; agroup_to_keylist(adt, agrp, &anim_keys, NULL); } else if (ale->type == ANIMTYPE_GPLAYER) { // TODO: why don't we just give gplayers key_data too? bGPDlayer *gpl = (bGPDlayer *)ale->data; gpl_to_keylist(ads, gpl, &anim_keys); } else if (ale->type == ANIMTYPE_MASKLAYER) { // TODO: why don't we just give masklayers key_data too? MaskLayer *masklay = (MaskLayer *)ale->data; mask_to_keylist(ads, masklay, &anim_keys); } /* start from keyframe at root of BST, traversing until we find one within the range that was clicked on */ for (ak = anim_keys.root; ak; ak = akn) { if (IN_RANGE(ak->cfra, rectf.xmin, rectf.xmax)) { /* set the frame to use, and apply inverse-correction for NLA-mapping * so that the frame will get selected by the selection functions without * requiring to map each frame once again... */ selx = BKE_nla_tweakedit_remap(adt, ak->cfra, NLATIME_CONVERT_UNMAP); frame = ak->cfra; found = true; break; } else if (ak->cfra < rectf.xmin) akn = ak->right; else akn = ak->left; } /* remove active channel from list of channels for separate treatment (since it's needed later on) */ BLI_remlink(&anim_data, ale); /* cleanup temporary lists */ BLI_dlrbTree_free(&anim_keys); /* free list of channels, since it's not used anymore */ ANIM_animdata_freelist(&anim_data); } /* for replacing selection, firstly need to clear existing selection */ if (select_mode == SELECT_REPLACE) { /* reset selection mode for next steps */ select_mode = SELECT_ADD; /* deselect all keyframes */ deselect_action_keys(ac, 0, SELECT_SUBTRACT); /* highlight channel clicked on */ if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)) { /* deselect all other channels first */ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); /* Highlight Action-Group or F-Curve? */ if (ale && ale->data) { if (ale->type == ANIMTYPE_GROUP) { bActionGroup *agrp = ale->data; agrp->flag |= AGRP_SELECTED; ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP); } else if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) { FCurve *fcu = ale->data; fcu->flag |= FCURVE_SELECTED; ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type); } } } else if (ac->datatype == ANIMCONT_GPENCIL) { /* deselect all other channels first */ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); /* Highlight GPencil Layer */ if ((ale && ale->data) && (ale->type == ANIMTYPE_GPLAYER)) { bGPDlayer *gpl = ale->data; gpl->flag |= GP_LAYER_SELECT; //gpencil_layer_setactive(gpd, gpl); } } else if (ac->datatype == ANIMCONT_MASK) { /* deselect all other channels first */ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); /* Highlight GPencil Layer */ if ((ale && ale->data) && (ale->type == ANIMTYPE_MASKLAYER)) { MaskLayer *masklay = ale->data; masklay->flag |= MASK_LAYERFLAG_SELECT; //gpencil_layer_setactive(gpd, gpl); } } } /* only select keyframes if we clicked on a valid channel and hit something */ if (ale) { if (found) { /* apply selection to keyframes */ if (column) { /* select all keyframes in the same frame as the one we hit on the active channel * [T41077]: "frame" not "selx" here (i.e. no NLA corrections yet) as the code here * does that itself again as it needs to work on multiple datablocks */ actkeys_mselect_column(ac, select_mode, frame); } else if (same_channel) { /* select all keyframes in the active channel */ actkeys_mselect_channel_only(ac, ale, select_mode); } else { /* select the nominated keyframe on the given frame */ actkeys_mselect_single(ac, ale, select_mode, selx); } } /* free this channel */ MEM_freeN(ale); } }
void qhsort(void* start, int n, int sz, int (*compar)(void* a, void* b, void* handle), void* handle) { byte *vec = (byte*) start; int left=1, right=n-1; const int pivot = 0; assert(sort_depth < 16); if (n <= 1) return; sort_depth++; while (left < right) { while (left < n && compar(ELEM(left), ELEM(pivot), handle) < 0) { left++; } while (right >= 0 && compar(ELEM(right), ELEM(pivot), handle) > 0) { right--; } if (left < right) { swapb(ELEM(left), ELEM(right), sz); } } if (compar(ELEM(right), ELEM(pivot), handle) < 0) { swapb(ELEM(right), ELEM(pivot), sz); } qhsort(start, right, sz, compar, handle); qhsort(ELEM(right+1), n-right-1, sz, compar, handle); sort_depth--; }
/* Selects all visible keyframes in the same frames as the specified elements */ static void columnselect_action_keys(bAnimContext *ac, short mode) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; Scene *scene = ac->scene; CfraElem *ce; KeyframeEditFunc select_cb, ok_cb; KeyframeEditData ked = {{NULL}}; /* build list of columns */ switch (mode) { case ACTKEYS_COLUMNSEL_KEYS: /* list of selected keys */ if (ac->datatype == ANIMCONT_GPENCIL) { filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); for (ale = anim_data.first; ale; ale = ale->next) ED_gplayer_make_cfra_list(ale->data, &ked.list, 1); } else { filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); for (ale = anim_data.first; ale; ale = ale->next) ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_to_cfraelem, NULL); } ANIM_animdata_freelist(&anim_data); break; case ACTKEYS_COLUMNSEL_CFRA: /* current frame */ /* make a single CfraElem for storing this */ ce = MEM_callocN(sizeof(CfraElem), "cfraElem"); BLI_addtail(&ked.list, ce); ce->cfra = (float)CFRA; break; case ACTKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */ ED_markers_make_cfra_list(ac->markers, &ked.list, SELECT); break; default: /* invalid option */ return; } /* set up BezTriple edit callbacks */ select_cb = ANIM_editkeyframes_select(SELECT_ADD); ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME); /* loop through all of the keys and select additional keyframes * based on the keys found to be selected above */ if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE); else filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); /* loop over cfraelems (stored in the KeyframeEditData->list) * - we need to do this here, as we can apply fewer NLA-mapping conversions */ for (ce = ked.list.first; ce; ce = ce->next) { /* set frame for validation callback to refer to */ if (adt) ked.f1 = BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP); else ked.f1 = ce->cfra; /* select elements with frame number matching cfraelem */ if (ale->type == ANIMTYPE_GPLAYER) ED_gpencil_select_frame(ale->data, ce->cfra, SELECT_ADD); else if (ale->type == ANIMTYPE_MASKLAYER) ED_mask_select_frame(ale->data, ce->cfra, SELECT_ADD); else ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); } } /* free elements */ BLI_freelistN(&ked.list); ANIM_animdata_freelist(&anim_data); }
/** * Calculate smooth groups from sharp edges. * * \param r_totgroup The total number of groups, 1 or more. * \return Polygon aligned array of group index values (bitflags if use_bitflags is true), starting at 1. */ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge, const MPoly *mpoly, const int totpoly, const MLoop *mloop, const int totloop, int *r_totgroup, const bool use_bitflags) { int *poly_groups; int *poly_stack; int poly_prev = 0; const int temp_poly_group_id = 3; /* Placeholder value. */ const int poly_group_id_overflowed = 5; /* Group we could not find any available bit, will be reset to 0 at end */ int tot_group = 0; bool group_id_overflow = false; /* map vars */ MeshElemMap *edge_poly_map; int *edge_poly_mem; if (totpoly == 0) { *r_totgroup = 0; return NULL; } BKE_mesh_edge_poly_map_create(&edge_poly_map, &edge_poly_mem, medge, totedge, mpoly, totpoly, mloop, totloop); poly_groups = MEM_callocN(sizeof(int) * (size_t)totpoly, __func__); poly_stack = MEM_mallocN(sizeof(int) * (size_t)totpoly, __func__); while (true) { int poly; int bit_poly_group_mask = 0; int poly_group_id; int ps_curr_idx = 0, ps_end_idx = 0; /* stack indices */ for (poly = poly_prev; poly < totpoly; poly++) { if (poly_groups[poly] == 0) { break; } } if (poly == totpoly) { /* all done */ break; } poly_group_id = use_bitflags ? temp_poly_group_id : ++tot_group; /* start searching from here next time */ poly_prev = poly + 1; poly_groups[poly] = poly_group_id; poly_stack[ps_end_idx++] = poly; while (ps_curr_idx != ps_end_idx) { const MPoly *mp; const MLoop *ml; bool sharp_poly; int j; poly = poly_stack[ps_curr_idx++]; BLI_assert(poly_groups[poly] == poly_group_id); mp = &mpoly[poly]; sharp_poly = !(mp->flag & ME_SMOOTH); for (ml = &mloop[mp->loopstart], j = mp->totloop; j--; ml++) { /* loop over poly users */ const MeshElemMap *map_ele = &edge_poly_map[ml->e]; const int *p = map_ele->indices; int i = map_ele->count; /* Edge is smooth only if its poly is not sharp, edge is not sharp, * and edge is used by exactly two polygons. */ if (!sharp_poly && !(medge[ml->e].flag & ME_SHARP) && i == 2) { for (; i--; p++) { /* if we meet other non initialized its a bug */ BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id)); if (poly_groups[*p] == 0) { poly_groups[*p] = poly_group_id; poly_stack[ps_end_idx++] = *p; } } } else if (use_bitflags) { /* Find contiguous smooth groups already assigned, these are the values we can't reuse! */ for (; i--; p++) { int bit = poly_groups[*p]; if (!ELEM(bit, 0, poly_group_id, poly_group_id_overflowed) && !(bit_poly_group_mask & bit)) { bit_poly_group_mask |= bit; } } } } } /* And now, we have all our poly from current group in poly_stack (from 0 to (ps_end_idx - 1)), as well as * all smoothgroups bits we can't use in bit_poly_group_mask. */ if (use_bitflags) { int i, *p, gid_bit = 0; poly_group_id = 1; /* Find first bit available! */ for (; (poly_group_id & bit_poly_group_mask) && (gid_bit < 32); gid_bit++) { poly_group_id <<= 1; /* will 'overflow' on last possible iteration. */ } if (UNLIKELY(gid_bit > 31)) { /* All bits used in contiguous smooth groups, we can't do much! * Note: this is *very* unlikely - theoretically, four groups are enough, I don't think we can reach * this goal with such a simple algo, but I don't think either we'll never need all 32 groups! */ printf("Warning, could not find an available id for current smooth group, faces will me marked " "as out of any smooth group...\n"); poly_group_id = poly_group_id_overflowed; /* Can't use 0, will have to set them to this value later. */ group_id_overflow = true; } if (gid_bit > tot_group) { tot_group = gid_bit; } /* And assign the final smooth group id to that poly group! */ for (i = ps_end_idx, p = poly_stack; i--; p++) { poly_groups[*p] = poly_group_id; } } } if (use_bitflags) { /* used bits are zero-based. */ tot_group++; } if (UNLIKELY(group_id_overflow)) { int i = totpoly, *gid = poly_groups; for (; i--; gid++) { if (*gid == poly_group_id_overflowed) { *gid = 0; } } /* Using 0 as group id adds one more group! */ tot_group++; } MEM_freeN(edge_poly_map); MEM_freeN(edge_poly_mem); MEM_freeN(poly_stack); *r_totgroup = tot_group; return poly_groups; }
static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(quad), int x, int y, float UNUSED(u), float UNUSED(v), float *tvn, float *ttang) { BakeShade *bs = handle; ShadeSample *ssamp = &bs->ssamp; ShadeResult shr; VlakRen *vlr = shi->vlr; shade_input_init_material(shi); if (bs->type == RE_BAKE_AO) { ambient_occlusion(shi); if (R.r.bake_flag & R_BAKE_NORMALIZE) { copy_v3_v3(shr.combined, shi->ao); } else { zero_v3(shr.combined); environment_lighting_apply(shi, &shr); } } else { if (bs->type == RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */ shi->r = shi->g = shi->b = 1.0f; shade_input_set_shade_texco(shi); /* only do AO for a full bake (and obviously AO bakes) * AO for light bakes is a leftover and might not be needed */ if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_AO, RE_BAKE_LIGHT)) shade_samples_do_AO(ssamp); if (shi->mat->nodetree && shi->mat->use_nodes) { ntreeShaderExecTree(shi->mat->nodetree, shi, &shr); shi->mat = vlr->mat; /* shi->mat is being set in nodetree */ } else shade_material_loop(shi, &shr); if (bs->type == RE_BAKE_NORMALS) { float nor[3]; copy_v3_v3(nor, shi->vn); if (R.r.bake_normal_space == R_BAKE_SPACE_CAMERA) { /* pass */ } else if (R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) { float mat[3][3], imat[3][3]; /* bitangent */ if (tvn && ttang) { copy_v3_v3(mat[0], ttang); cross_v3_v3v3(mat[1], tvn, ttang); mul_v3_fl(mat[1], ttang[3]); copy_v3_v3(mat[2], tvn); } else { copy_v3_v3(mat[0], shi->nmaptang); cross_v3_v3v3(mat[1], shi->nmapnorm, shi->nmaptang); mul_v3_fl(mat[1], shi->nmaptang[3]); copy_v3_v3(mat[2], shi->nmapnorm); } invert_m3_m3(imat, mat); mul_m3_v3(imat, nor); } else if (R.r.bake_normal_space == R_BAKE_SPACE_OBJECT) mul_mat3_m4_v3(ob->imat_ren, nor); /* ob->imat_ren includes viewinv! */ else if (R.r.bake_normal_space == R_BAKE_SPACE_WORLD) mul_mat3_m4_v3(R.viewinv, nor); normalize_v3(nor); /* in case object has scaling */ /* The invert of the red channel is to make * the normal map compliant with the outside world. * It needs to be done because in Blender * the normal used in the renderer points inward. It is generated * this way in calc_vertexnormals(). Should this ever change * this negate must be removed. */ shr.combined[0] = (-nor[0]) / 2.0f + 0.5f; shr.combined[1] = nor[1] / 2.0f + 0.5f; shr.combined[2] = nor[2] / 2.0f + 0.5f; } else if (bs->type == RE_BAKE_TEXTURE) { copy_v3_v3(shr.combined, &shi->r); shr.alpha = shi->alpha; } else if (bs->type == RE_BAKE_SHADOW) { copy_v3_v3(shr.combined, shr.shad); shr.alpha = shi->alpha; } else if (bs->type == RE_BAKE_SPEC_COLOR) { copy_v3_v3(shr.combined, &shi->specr); shr.alpha = 1.0f; } else if (bs->type == RE_BAKE_SPEC_INTENSITY) { copy_v3_fl(shr.combined, shi->spec); shr.alpha = 1.0f; } else if (bs->type == RE_BAKE_MIRROR_COLOR) { copy_v3_v3(shr.combined, &shi->mirr); shr.alpha = 1.0f; } else if (bs->type == RE_BAKE_MIRROR_INTENSITY) { copy_v3_fl(shr.combined, shi->ray_mirror); shr.alpha = 1.0f; } else if (bs->type == RE_BAKE_ALPHA) { copy_v3_fl(shr.combined, shi->alpha); shr.alpha = 1.0f; } else if (bs->type == RE_BAKE_EMIT) { copy_v3_fl(shr.combined, shi->emit); shr.alpha = 1.0f; } else if (bs->type == RE_BAKE_VERTEX_COLORS) { copy_v3_v3(shr.combined, shi->vcol); shr.alpha = shi->vcol[3]; } } if (bs->rect_float && !bs->vcol) { float *col = bs->rect_float + 4 * (bs->rectx * y + x); copy_v3_v3(col, shr.combined); if (bs->type == RE_BAKE_ALL || bs->type == RE_BAKE_TEXTURE || bs->type == RE_BAKE_VERTEX_COLORS) { col[3] = shr.alpha; } else { col[3] = 1.0; } } else { /* Target is char (LDR). */ unsigned char col[4]; if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) { float rgb[3]; copy_v3_v3(rgb, shr.combined); if (R.scene_color_manage) { /* Vertex colors have no way to specify color space, so they * default to sRGB. */ if (!bs->vcol) IMB_colormanagement_scene_linear_to_colorspace_v3(rgb, bs->rect_colorspace); else linearrgb_to_srgb_v3_v3(rgb, rgb); } rgb_float_to_uchar(col, rgb); } else { rgb_float_to_uchar(col, shr.combined); } if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE, RE_BAKE_VERTEX_COLORS)) { col[3] = FTOCHAR(shr.alpha); } else { col[3] = 255; } if (bs->vcol) { /* Vertex color baking. Vcol has no useful alpha channel (it exists * but is used only for vertex painting). */ bs->vcol->r = col[0]; bs->vcol->g = col[1]; bs->vcol->b = col[2]; } else { unsigned char *imcol = (unsigned char *)(bs->rect + bs->rectx * y + x); copy_v4_v4_char((char *)imcol, (char *)col); } } if (bs->rect_mask) { bs->rect_mask[bs->rectx * y + x] = FILTER_MASK_USED; } if (bs->do_update) { *bs->do_update = true; } }
PRUint32 mGroup; PRUint32 mCanContainGroups; PRPackedBool mIsContainer; PRPackedBool mCanContainSelf; }; #ifdef DEBUG #define ELEM(_tag, _isContainer, _canContainSelf, _group, _canContainGroups) \ { eHTMLTag_##_tag, _group, _canContainGroups, _isContainer, _canContainSelf } #else #define ELEM(_tag, _isContainer, _canContainSelf, _group, _canContainGroups) \ { _group, _canContainGroups, _isContainer, _canContainSelf } #endif static const nsElementInfo kElements[eHTMLTag_userdefined] = { ELEM(a, PR_TRUE, PR_FALSE, GROUP_SPECIAL, GROUP_INLINE_ELEMENT), ELEM(abbr, PR_TRUE, PR_TRUE, GROUP_PHRASE, GROUP_INLINE_ELEMENT), ELEM(acronym, PR_TRUE, PR_TRUE, GROUP_PHRASE, GROUP_INLINE_ELEMENT), ELEM(address, PR_TRUE, PR_TRUE, GROUP_BLOCK, GROUP_INLINE_ELEMENT | GROUP_P), ELEM(applet, PR_TRUE, PR_TRUE, GROUP_SPECIAL | GROUP_BLOCK, GROUP_FLOW_ELEMENT | GROUP_OBJECT_CONTENT), ELEM(area, PR_FALSE, PR_FALSE, GROUP_MAP_CONTENT, GROUP_NONE), ELEM(b, PR_TRUE, PR_TRUE, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT), ELEM(base, PR_FALSE, PR_FALSE, GROUP_HEAD_CONTENT, GROUP_NONE), ELEM(basefont, PR_FALSE, PR_FALSE, GROUP_SPECIAL, GROUP_NONE), ELEM(bdo, PR_TRUE, PR_TRUE, GROUP_SPECIAL, GROUP_INLINE_ELEMENT), ELEM(bgsound, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), ELEM(big, PR_TRUE, PR_TRUE, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT), ELEM(blink, PR_FALSE, PR_FALSE, GROUP_NONE, GROUP_NONE), ELEM(blockquote, PR_TRUE, PR_TRUE, GROUP_BLOCK, GROUP_FLOW_ELEMENT),