static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit, char *numstr, size_t numstr_size, int prec) { const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0; if (ruler_item->flag & RULERITEM_USE_ANGLE) { const float ruler_angle = angle_v3v3v3(ruler_item->co[0], ruler_item->co[1], ruler_item->co[2]); if (unit->system == USER_UNIT_NONE) { BLI_snprintf(numstr, numstr_size, "%.*f°", prec, RAD2DEGF(ruler_angle)); } else { bUnit_AsString(numstr, numstr_size, (double)ruler_angle, prec, unit->system, B_UNIT_ROTATION, do_split, false); } } else { const float ruler_len = len_v3v3(ruler_item->co[0], ruler_item->co[2]); if (unit->system == USER_UNIT_NONE) { BLI_snprintf(numstr, numstr_size, "%.*f", prec, ruler_len); } else { bUnit_AsString(numstr, numstr_size, (double)(ruler_len * unit->scale_length), prec, unit->system, B_UNIT_LENGTH, do_split, false); } } }
/* str must be NUM_STR_REP_LEN * (idx_max + 1) length. */ void outputNumInput(NumInput *n, char *str) { short i, j; const int ln = NUM_STR_REP_LEN; int prec = 2; /* draw-only, and avoids too much issues with radian->degrees conversion. */ for (j = 0; j <= n->idx_max; j++) { /* if AFFECTALL and no number typed and cursor not on number, use first number */ i = (n->flag & NUM_AFFECT_ALL && n->idx != j && !(n->val_flag[j] & NUM_EDITED)) ? 0 : j; if (n->val_flag[i] & NUM_EDITED) { /* Get the best precision, allows us to draw '10.0001' as '10' instead! */ prec = uiFloatPrecisionCalc(prec, (double)n->val[i]); if (i == n->idx) { const char *heading_exp = "", *trailing_exp = ""; char before_cursor[NUM_STR_REP_LEN]; char val[16]; if (n->val_flag[i] & NUM_NEGATE) { heading_exp = (n->val_flag[i] & NUM_INVERSE) ? "-1/(" : "-("; trailing_exp = ")"; } else if (n->val_flag[i] & NUM_INVERSE) { heading_exp = "1/("; trailing_exp = ")"; } if (n->val_flag[i] & NUM_INVALID) { BLI_strncpy(val, "Invalid", sizeof(val)); } else { bUnit_AsString(val, sizeof(val), (double)n->val[i], prec, n->unit_sys, n->unit_type[i], true, false); } BLI_strncpy(before_cursor, n->str, n->str_cur + 1); /* +1 because of trailing '\0' */ BLI_snprintf(&str[j * ln], ln, "[%s%s|%s%s] = %s", heading_exp, before_cursor, &n->str[n->str_cur], trailing_exp, val); } else { const char *cur = (i == n->idx) ? "|" : ""; if (n->unit_use_radians && n->unit_type[i] == B_UNIT_ROTATION) { /* Radian exception... */ BLI_snprintf(&str[j * ln], ln, "%s%.6gr%s", cur, n->val[i], cur); } else { char tstr[NUM_STR_REP_LEN]; bUnit_AsString(tstr, ln, (double)n->val[i], prec, n->unit_sys, n->unit_type[i], true, false); BLI_snprintf(&str[j * ln], ln, "%s%s%s", cur, tstr, cur); } } } else { const char *cur = (i == n->idx) ? "|" : ""; BLI_snprintf(&str[j * ln], ln, "%sNONE%s", cur, cur); } /* We might have cut some multi-bytes utf8 chars (e.g. trailing '°' of degrees values can become only 'A')... */ BLI_utf8_invalid_strip(&str[j * ln], strlen(&str[j * ln])); } }
static PyObject *bpyunits_to_string(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { static const char *kwlist[] = {"unit_system", "unit_category", "value", "precision", "split_unit", "compatible_unit", NULL}; char *usys_str = NULL, *ucat_str = NULL; double value = 0.0; int precision = 3; bool split_unit = false, compatible_unit = false; int usys, ucat; if (!PyArg_ParseTupleAndKeywords( args, kw, "ssd|iO&O&:bpy.utils.units.to_string", (char **)kwlist, &usys_str, &ucat_str, &value, &precision, PyC_ParseBool, &split_unit, PyC_ParseBool, &compatible_unit)) { return NULL; } if (!bpyunits_validate(usys_str, ucat_str, &usys, &ucat)) { return NULL; } { /* Maximum expected length of string result: * - number itself: precision + decimal dot + up to four 'above dot' digits. * - unit: up to ten chars (six currently, let's be conservative, also because we use some utf8 chars). * This can be repeated twice (e.g. 1m20cm), and we add ten more spare chars (spaces, trailing '\0'...). * So in practice, 64 should be more than enough. */ char buf1[64], buf2[64], *str; PyObject *result; bUnit_AsString(buf1, sizeof(buf1), value, precision, usys, ucat, (bool)split_unit, false); if (compatible_unit) { bUnit_ToUnitAltName(buf2, sizeof(buf2), buf1, usys, ucat); str = buf2; } else { str = buf1; } result = PyUnicode_FromString(str); return result; } }
static void value_to_editstr(NumInput *n, int idx) { const int prec = 6; /* editing, higher precision needed. */ n->str_cur = bUnit_AsString(n->str, NUM_STR_REP_LEN, (double)n->val[idx], prec, n->unit_sys, n->unit_type[idx], true, false); }
/** * \brief get the ID from the screen. * */ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, int my, float *r_depth) { /* we could use some clever */ wmWindow *win = CTX_wm_window(C); ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, mx, my); Scene *scene = win->screen->scene; UnitSettings *unit = &scene->unit; const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0; ScrArea *area_prev = CTX_wm_area(C); ARegion *ar_prev = CTX_wm_region(C); ddr->name[0] = '\0'; if (sa) { if (sa->spacetype == SPACE_VIEW3D) { ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); if (ar) { View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; /* weak, we could pass in some reference point */ const float *view_co = v3d->camera ? v3d->camera->obmat[3] : rv3d->viewinv[3]; const int mval[2] = { mx - ar->winrct.xmin, my - ar->winrct.ymin}; float co[3]; CTX_wm_area_set(C, sa); CTX_wm_region_set(C, ar); /* grr, always draw else we leave stale text */ ED_region_tag_redraw(ar); view3d_operator_needs_opengl(C); if (ED_view3d_autodist(scene, ar, v3d, mval, co, true, NULL)) { const float mval_center_fl[2] = { (float)ar->winx / 2, (float)ar->winy / 2}; float co_align[3]; /* quick way to get view-center aligned point */ ED_view3d_win_to_3d(ar, co, mval_center_fl, co_align); *r_depth = len_v3v3(view_co, co_align); bUnit_AsString(ddr->name, sizeof(ddr->name), (double)*r_depth, 4, unit->system, B_UNIT_LENGTH, do_split, false); } else { BLI_strncpy(ddr->name, "Nothing under cursor", sizeof(ddr->name)); } } } } CTX_wm_area_set(C, area_prev); CTX_wm_region_set(C, ar_prev); }