[Bf-blender-cvs] [ffb5154] ui_layout_gridflow: Factorize gridflow computation code.

Bastien Montagne noreply at git.blender.org
Sun Dec 4 12:45:58 CET 2016


Commit: ffb515410c113195ff9c2f06f39e91879630c1e1
Author: Bastien Montagne
Date:   Thu Dec 1 23:00:57 2016 +0100
Branches: ui_layout_gridflow
https://developer.blender.org/rBffb515410c113195ff9c2f06f39e91879630c1e1

Factorize gridflow computation code.

===================================================================

M	release/scripts/startup/bl_ui/properties_data_mesh.py
M	source/blender/editors/interface/interface_layout.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index c7b931e..1ff84bc 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -213,14 +213,14 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
             col.operator("object.vertex_group_move", icon='TRIA_UP', text="").direction = 'UP'
             col.operator("object.vertex_group_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
 
-        gflow = layout.grid_flow(row_major=True, num_columns=-2, align=True, even_columns=False, even_rows=True)
+        gflow = layout.grid_flow(row_major=True, num_columns=0, align=False, even_columns=False, even_rows=False)
         for vg in ob.vertex_groups:
             gflow.prop(vg, "name", text="")
             gflow.prop(vg, "lock_weight")
 
         layout.separator()
 
-        gflow = layout.grid_flow(row_major=False, num_columns=-2, align=True, even_columns=False, even_rows=True)
+        gflow = layout.grid_flow(row_major=False, num_columns=0, align=False, even_columns=False, even_rows=False)
         for vg in ob.vertex_groups:
             gflow.prop(vg, "name", text="")
             gflow.prop(vg, "lock_weight")
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 2c7a23c..ee8fb10 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -2530,38 +2530,157 @@ static void ui_litem_layout_column_flow(uiLayout *litem)
 	litem->y = miny;
 }
 
-/* multi-column layout, automatically flowing to the next */
-static void ui_litem_estimate_grid_flow(uiLayout *litem)
+/* multi-column and multi-row layout. */
+static void ui_litem_grid_flow_compute(
+        ListBase *items, int *r_tot_items, const bool row_major, const bool even_cols, const bool even_rows,
+        const int litem_w, const int litem_x, const int litem_y, const int space_x, const int space_y,
+        float *r_global_avg_w, const int tot_cols, int *r_cos_x, int *r_widths, int *r_tot_w,
+        float *r_global_avg_h, const int tot_rows, int *r_cos_y, int *r_heights, int *r_tot_h)
 {
-	uiStyle *style = litem->root->style;
-	uiLayoutItemGridFlow *gflow = (uiLayoutItemGridFlow *)litem;
 	uiItem *item;
 	int i;
 
-	/* Estimate average needed width and height per item.
-	 * To do so, we do a weighted average where dimension of an item is its own weight.
-	 * This allows us to give more importance to big items, while not using actual biggest size as reference
-	 * (e.g. if we have a fair amount of very wide items, computed average width will be very close to their width,
-	 * but if we only have one very wide one, and many narrower ones, then we'll contraint the widest into reasonably
-	 * smaller space, to avoid too much emptyness in other cells). */
-	{
-		gflow->tot_items = 0;
-		float avg_w = 0.0f;
-		float avg_h = 0.0f;
-		float totweight_w = 0.0f;
-		float totweight_h = 0.0f;
-		for (item = litem->items.first, gflow->tot_items = 0; item; item = item->next, gflow->tot_items++) {
-			int item_w, item_h;
-			ui_item_size(item, &item_w, &item_h);
+	int tot_w = 0.0f, tot_h = 0.0f;
+	float global_avg_w = 0.0f, global_avg_h = 0.0f;
+	float global_totweight_w = 0.0f, global_totweight_h = 0.0f;
+
+	float *avg_w = NULL;
+	float *totweight_w = NULL;
+	float *avg_h = NULL;
+	float *totweight_h = NULL;
+
+	BLI_assert(tot_cols != 0 || (avg_w == NULL && r_cos_x == NULL && r_widths == NULL));
+	BLI_assert(tot_rows != 0 || (avg_h == NULL && r_cos_y == NULL && r_heights == NULL));
+
+	if (r_tot_items) {
+		*r_tot_items = 0;
+	}
+
+	if (tot_cols != 0) {
+		avg_w = alloca(sizeof(*avg_w) * tot_cols);
+		totweight_w = alloca(sizeof(*totweight_w) * tot_cols);
+		memset(avg_w, 0, sizeof(*avg_w) * tot_cols);
+		memset(totweight_w, 0, sizeof(*totweight_w) * tot_cols);
+	}
+	if (tot_rows != 0) {
+		avg_h = alloca(sizeof(*avg_h) * tot_rows);
+		totweight_h = alloca(sizeof(*totweight_h) * tot_rows);
+		memset(avg_h, 0, sizeof(*avg_h) * tot_rows);
+		memset(totweight_h, 0, sizeof(*totweight_h) * tot_rows);
+	}
+
+	for (i = 0, item = items->first; item; item = item->next, i++) {
+		int item_w, item_h;
+		ui_item_size(item, &item_w, &item_h);
+
+		global_avg_w += (float)(item_w * item_w);
+		global_totweight_w += (float)item_w;
+		global_avg_h += (float)(item_h * item_h);
+		global_totweight_h += (float)item_h;
+
+		if (tot_rows != 0 && tot_cols != 0) {
+			const int index_col = row_major ? i % tot_cols : i / tot_rows;
+			const int index_row = row_major ? i / tot_cols : i % tot_rows;
+
+			avg_w[index_col] += (float)(item_w * item_w);
+			totweight_w[index_col] += (float)item_w;
+
+			avg_h[index_row] += (float)(item_h * item_h);
+			totweight_h[index_row] += (float)item_h;
+		}
+
+		if (r_tot_items) {
+			(*r_tot_items)++;
+		}
+	}
 
-			avg_w += (float)(item_w * item_w);
-			totweight_w += (float)item_w;
+	/* Finalize computing of column average sizes */
+	global_avg_w /= global_totweight_w;
+	if (tot_cols != 0) {
+		for (i = 0; i < tot_cols; i++) {
+			avg_w[i] /= totweight_w[i];
+			tot_w += avg_w[i];
+		}
+		if (even_cols) {
+			tot_w = (int)(ceilf(global_avg_w) * tot_cols);
+		}
+	}
+	/* Finalize computing of rows average sizes */
+	global_avg_h /= global_totweight_h;
+	if (tot_rows != 0) {
+		for (i = 0; i < tot_rows; i++) {
+			avg_h[i] /= totweight_h[i];
+			tot_h += avg_h[i];
+		}
+		if (even_cols) {
+			tot_h = (int)(ceilf(global_avg_h) * tot_rows);
+		}
+	}
+
+	/* Compute positions and sizes of all cells. */
+	if (r_cos_x != NULL && r_widths != NULL) {
+		/* We enlarge/narrow columns evenly to match available width. */
+		const float wfac = (float)(litem_w - (tot_cols - 1) * space_x) / tot_w;
 
-			avg_h += (float)(item_h * item_h);
-			totweight_h += (float)item_h;
+		for (int col = 0; col < tot_cols; col++) {
+			r_cos_x[col] = col ? r_cos_x[col - 1] + r_widths[col - 1] + space_x : litem_x;
+			if (even_cols) {
+				/*              (<        remaining width         > - <space between remain columns>) / <remain columns> */
+				r_widths[col] = ((litem_w - (r_cos_x[col] - litem_x)) - (tot_cols - col - 1) * space_x) / (tot_cols - col);
+			}
+			else if (col == tot_cols - 1) {
+				/* Last column copes width rounding errors... */
+				r_widths[col] = litem_w - (r_cos_x[col] - litem_x);
+			}
+			else {
+				r_widths[col] = (int)(avg_w[col] * wfac);
+			}
+		}
+	}
+	if (r_cos_y != NULL && r_heights != NULL) {
+		const int even_h = (int)ceilf(global_avg_h);
+		for (int row = 0; row < tot_rows; row++) {
+			if (even_rows) {
+				r_heights[row] = even_h;
+			}
+			else {
+				r_heights[row] = (int)avg_h[row];
+			}
+			r_cos_y[row] = row ? r_cos_y[row - 1] - r_heights[row - 1] - space_y : litem_y - r_heights[row];
 		}
-		avg_w /= totweight_w;
-		avg_h /= totweight_h;
+	}
+
+	if (r_global_avg_w) {
+		*r_global_avg_w = global_avg_w;
+	}
+	if (r_global_avg_h) {
+		*r_global_avg_h = global_avg_h;
+	}
+	if (r_tot_w) {
+		*r_tot_w = tot_w + space_x * (tot_cols - 1);
+	}
+	if (r_tot_h) {
+		*r_tot_h = tot_h + space_y * (tot_rows - 1);
+	}
+}
+
+static void ui_litem_estimate_grid_flow(uiLayout *litem)
+{
+	uiStyle *style = litem->root->style;
+	uiLayoutItemGridFlow *gflow = (uiLayoutItemGridFlow *)litem;
+
+	const int space_x = style->columnspace;
+	const int space_y = style->buttonspacey;
+
+	/* Estimate average needed width and height per item. */
+	{
+		float avg_w, avg_h;
+
+		ui_litem_grid_flow_compute(
+		        &litem->items, &gflow->tot_items, gflow->row_major, gflow->even_columns, gflow->even_rows,
+		        litem->w, litem->x, litem->y, space_x, space_y,
+		        &avg_w, 0, NULL, NULL, NULL,
+		        &avg_h, 0, NULL, NULL, NULL);
 
 		/* Even in varying column width case, we fix our columns number from weighted average width of items,
 		 * a proper solving of required width would be too costly, and this should give reasonably good results
@@ -2577,27 +2696,28 @@ static void ui_litem_estimate_grid_flow(uiLayout *litem)
 				gflow->tot_columns = min_ii(max_ii((int)(litem->w / avg_w), 1), gflow->tot_items);
 			}
 		}
-		gflow->tot_rows = (int)ceilf((float)gflow->tot_items / gflow->tot_columns);
 
+		/* In column major case, we may need to adjust number of columns, e.g. with 8 items, if we auto-compute
+		 * 5 columns, we can only actually fill 4 of them (since we need 2 rows anyway)... */
 		if (!gflow->row_major && gflow->num_columns <= 0) {
-			/* In column major case, we may need to adjust number of columns, e.g. with 8 items, if we auto-compute
-			 * 5 columns, we can only actually fill 4 of them (since we need 2 rows anyway)... */
+			gflow->tot_rows = (int)ceilf((float)gflow->tot_items / gflow->tot_columns);
 			gflow->tot_columns = (int)ceilf((float)gflow->tot_items / gflow->tot_rows);
 		}
 
+		/* 'Modulo' number of columns as last step. */
 		if (gflow->num_columns < -1) {
 			const int modulo = -gflow->num_columns;
 			gflow->tot_columns = max_ii(modulo, gflow->tot_columns - (gflow->tot_columns % modulo));
-			/* Might have changed on the road... */
-			gflow->tot_rows = (int)ceilf((float)gflow->tot_items / gflow->tot_columns);
 		}
 
+		gflow->tot_rows = max_ii((int)ceilf((float)gflow->tot_items / gflow->tot_columns), 1);
+
 		/* Set evenly-spaced axes size. */
 		if (gflow->even_columns) {
-			litem->w = (int)(gflow->tot_columns * avg_w) + style->columnspace * (gflow->tot_columns - 1);
+			litem->w = (int)(gflow->tot_columns * avg_w) + space_x * (gflow->tot_columns - 1);
 		}
 		if (gflow->even_rows) {
-			litem->h = (int)(gflow->tot_rows * avg_h) + style->buttonspacey * (gflow->tot_rows - 1);
+			litem->h = (int)(gflow->tot_rows * avg_h) + space_y * (gflow->tot_rows - 1);
 
 			/* If columns' width and rows' height are even, we are done. */
 			if (gflow->even_columns) {
@@ -2606,70 +2726,19 @@ static void ui_litem_estimate_grid_flow(uiLayout *litem)
 		}
 	}
 
-	/* Compute actual needed space for non-evenly spaced axes. */
+	/* Now that we have our final number of columns and rows,
+	 * we can compute actual needed space for non-evenly sized axes. */
 	{
-		const bool use_dim1 = gflow->row_major ?

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list