Nested For Loops - generating a catan-style hex-grid in Unity - c#

As the title suggests, I am trying to generate a procedural hex grid in Unity using C#.
void Start ()
{
//5 mid
startRowSize = 5;
for (int i = 0; i < startRowSize; i++)
{
GameObject newHex = (GameObject)Instantiate(hex);
hexWidth = newHex.gameObject.renderer.bounds.size.z;
newHex.transform.Rotate(new Vector3(0,30,0));
newHex.transform.position = new Vector3((i * hexWidth),0,0);
}
for (int row = 0; row <= startRowSize-1; row ++)
{
for (int i = 0; i < row; i++)
{
GameObject newHex = (GameObject)Instantiate(hex);
newHex.transform.Rotate(new Vector3(0,30,0));
newHex.transform.position = new Vector3(((i*hexWidth)+((hexWidth/2))+(row*(hexWidth/2))),0,((startRowSize-row))*-(hexWidth/1.17f));
}
}
}
The code works, however the rows are being generated "backwards", meaning the outer rows contain the higher amounts of hexes, while the inner rows contain the smallest.
This is obviously the opposite effect that I am trying to achieve. I've been messing with this code for hours and I can't figure out why.
Any thoughts?

So after a few more hours of messing around with the code, I figured out why it wasn't iterating properly. He's the refined code...
void Start ()
{
//5 mid
startRowSize = 10;
for (int i = 0; i < startRowSize; i++)
{
GameObject newHex = (GameObject)Instantiate(hex);
hexWidth = newHex.gameObject.renderer.bounds.size.z;
newHex.transform.Rotate(new Vector3(0,30,0));
newHex.transform.position = new Vector3((i * hexWidth),0,0);
}
for (int row = 0; row < startRowSize; row++)
{
for (int i = 0; i < startRowSize-1-row; i++)
{
GameObject newHex = (GameObject)Instantiate(hex);
newHex.transform.Rotate(new Vector3(0,30,0));
if (row == 0)
{
newHex.transform.position = new Vector3(((i*hexWidth)+(hexWidth/2)),0,-(hexWidth/1.17f));
}
else
{
newHex.transform.position = new Vector3((i*hexWidth)+((row+1)*(hexWidth/2)),0,(row+1)*-(hexWidth/1.17f));
}
}
}
for (int row = 0; row < startRowSize; row++)
{
for (int i = 0; i < startRowSize-1-row; i++)
{
GameObject newHex = (GameObject)Instantiate(hex);
newHex.transform.Rotate(new Vector3(0,30,0));
if (row == 0)
{
newHex.transform.position = new Vector3(((i*hexWidth)+(hexWidth/2)),0,(hexWidth/1.17f));
}
else
{
newHex.transform.position = new Vector3((i*hexWidth)+((row+1)*(hexWidth/2)),0,(row+1)*(hexWidth/1.17f));
}
}
}
}
Now, can anyone suggest how to clean it up a bit? My brain is fizzled...

Just a tip, Awake happens before Start().
void Awake()
{
//5 mid
startRowSize = 10;
for (int i = 0; i < startRowSize; i++)
{
GameObject newHex = HexCreator();
hexWidth = newHex.gameObject.renderer.bounds.size.z;
newHex.transform.position = new Vector3(i * hexWidth, 0, 0);
}
for (int row = 0; row < startRowSize; row++)
for (int i = 0; i < startRowSize-1-row; i++)
{
GameObject newHex = HexCreator();
if (row == 0)
newHex.transform.position = new Vector3(i*hexWidth + hexWidth/2, 0, -(hexWidth/1.17f));
else
newHex.transform.position = new Vector3(i*hexWidth + ((row+1)*(hexWidth/2)), 0,(row+1)*-(hexWidth/1.17f));
}
for (int row = 0; row < startRowSize; row++)
for (int i = 0; i < startRowSize-1-row; i++)
{
GameObject newHex = HexCreator();
if (row == 0)
newHex.transform.position = new Vector3(i*hexWidth+ hexWidth/2, 0, hexWidth/1.17f);
else
newHex.transform.position = new Vector3(i*hexWidth + ((row+1)*(hexWidth/2)), 0, (row+1)*(hexWidth/1.17f));
}
}
Since you have this code repeating I made it into a function. That way if you need to upgrade it all you do is go to the function and change it there.
private GameObject HexCreator()
{
GameObject newHex = (GameObject)Instantiate(hex);
newHex.transform.Rotate(new Vector3(0,30,0));
return newHex;
}

Related

C# how to do arithmetic operations on a 2d Array matrix

I've been toying with this code which prints a small matrix with negative and positive numbers,
I would like an efficient way to add together only the positive elements on the matrix and get the product of such elements also do the same but after a specific number, such as the highest on the matrix
static void Main(string[] args)
{
int row = 5;
int column = 5;
int[,] array = new int[row, column];
Random rand = new Random();
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
array[i, j] = rand.Next(-5, 10);
}
}
for (int i = 0; i < array.GetLength(0); i++)
{
for (int j = 0; j < array.GetLength(1); j++)
{
Console.Write(array[i, j].ToString() + " ");
}
Console.WriteLine(" ");
}
Console.ReadLine();
}
To filter and add positive matrix elements, you could do something like the following:
static void Main(string[] args)
{
const int rows = 5;
const int columns = 5;
var array = new int[rows, columns];
var rand = new Random();
int sum = 0;
bool numberSeen = false;
int numberToSee = 1;
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < columns; col++)
{
var cell = rand.Next(-5, 10);
if (!numberSeen && (cell == numberToSee))
{
numberSeen = true;
}
array[row, col] = cell;
if (numberSeen && (cell > 0))
{
sum += cell;
}
}
}
Console.WriteLine($"sum = {sum}");
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < columns; col++)
{
Console.Write(array[row, col].ToString() + " ");
}
Console.WriteLine(" ");
}
Console.ReadLine();
}

NullReferenceException in child class when referring to member of parent [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 4 years ago.
Pretty much the title. I first set it in the first method and as soon as I wanna call it up it says it´s empty. Even in the Inspector it says that it´s set to the right thing but it can´t be called for some reason.
The two relevant code snippets:
public class WUZ_Unit : Leader
{
public override void UpdatePosition()
{
vecPos = GameObject.Find("WUZ(Clone)").transform.position;
Debug.Log(this + " the grid: " + grid);
**position = grid.GetNode((int)vecPos.x, (int)vecPos.y);**
}
}
and:
public abstract class Entity : MonoBehaviour {
public void InitiateGrid(Gridmanager g)
{
anim = GetComponent<Animator>();
if (anim.gameObject.activeSelf)
{
anim.SetBool("IsAlive", true);
}
grid = g;
Debug.Log(this + " set " + grid);
}
}
what the console spits out on the first Debug Log:
and what the console spits out on the second Debug Log:
This is the Error Code in Text:
NullReferenceException: Object reference not set to an instance of an object
WUZ_Unit.UpdatePosition () (at Assets/Scripts/Unit/WUZ_Unit.cs:21)
GameHandler.UpdateAllMoves () (at Assets/Scripts/GameHandler.cs:1805)
GameHandler.Start () (at Assets/Scripts/GameHandler.cs:1697)
The asked for code regarding instantiation:
public void GenerateCharacters(int x, int y, GameObject c, int i)
{
GameObject go = Instantiate(c) as GameObject;
//Entity e = go.GetComponent<Entity>();
//StartCoroutine(e.SpawnAnim());
if (i == 0)
{
Unit u = go.GetComponent<Unit>();
go.GetComponent<Enemy>().enabled = false;
u.enabled = true;
u.InitializeUnits();
u.healthBarEnemy = healthBarEnemy;
u.healthBarAlly = healthBarAlly;
u.healthMeter = healthbarMeter;
u.highlightAttack = highlightAttack;
u.highlightIndicator = highlightIndicator;
u.highlightMove = highlightMove;
u.InitiateGrid(grid);
u.SetPos(x, y);
GeneratePosition(u, x, y);
u.PlayerChange(gamePhase);
go.GetComponent<Enemy>().enabled = false;
}
This is the asked for code regarding updateposition:
public void UpdateAllMoves()
{
Debug.Log("updating all moves");
//Updating the grid status
grid.UpdatePosition();
Unit[] ul = unitList.ToArray();
for (int i = 0; i < ul.Length; i++)
{
ul[i].UpdatePosition();
}
Enemy[] el = enemyList.ToArray();
for (int i = 0; i < el.Length; i++)
{
el[i].UpdatePosition();
}
CheckforCheckUnit(grid);
CheckforCheckEnemy(grid);
ConvertAllMoves();
grid.ClearNodeMoves();
grid.UpdatePosition();
UpdateNodes();
grid.UpdatePosition();
for (int i = 0; i < ul.Length; i++)
{
**ul[i].UpdatePosition();**
}
for (int i = 0; i < el.Length; i++)
{
el[i].UpdatePosition();
}
CheckforCheckUnit(grid);
CheckforCheckEnemy(grid);
ConvertAllMoves();
grid.ClearNodeMoves();
grid.UpdatePosition();
UpdateNodes();
}
so I made sure that vecPos is not the problem:
Debug.Log(this + " the grid: " + grid + " the vecPos " + vecPos.x + " " + vecPos.y);
What the console spits out:
WUZ (WUZ_Unit) the grid: the vecPos 2 28
UnityEngine.Debug:Log(Object)
WUZ_Unit:UpdatePosition() (at Assets/Scripts/Unit/WUZ_Unit.cs:20)
GameHandler:UpdateAllMoves() (at Assets/Scripts/GameHandler.cs:1805)
GameHandler:Start() (at Assets/Scripts/GameHandler.cs:1697)
more clarification code:
public void GettingCharacters()
{
Debug.Log(StaticPara.player1Units.Length);
for(int i = 0; StaticPara.player1Units.Length > i; i++)
{
unitList.Add(StaticPara.player1Units[i].GetComponent<Unit>());
int x = startingTilesBlue[i].xPos;
int y = startingTilesBlue[i].yPos;
GenerateCharacters(x, y, StaticPara.player1Units[i], 0);
}
for (int i = 0; StaticPara.player2Units.Length > i; i++)
{
enemyList.Add(StaticPara.player2Units[i].GetComponent<Enemy>());
int x = startingTilesRed[i].xPos;
int y = startingTilesRed[i].yPos;
GenerateCharacters(x, y, StaticPara.player2Units[i], 1);
}
}
void Start()
{
grid = gridGO.GetComponent<Gridmanager>();
grid.CreateGrid();
//setting up ui and the game
gamePhase = 0;
phaseStatusString = "Move Phase";
endPhaseButton.GetComponent<Button>().interactable = false;
ability_ALX = true;
//spawning character Models
GenerateStartingPositions();
GettingCharacters();
//Updating their stats
Unit[] ul = unitList.ToArray();
for (int i = 0; i < ul.Length; i++)
{
ul[i].healthMax = ul[i].healthBase;
ul[i].healthCurrent = ul[i].healthMax;
ul[i].damageCurrent = ul[i].damageBase;
}
Enemy[] el = enemyList.ToArray();
for (int i = 0; i < el.Length; i++)
{
el[i].healthMax = el[i].healthBase;
el[i].healthCurrent = el[i].healthMax;
el[i].damageCurrent = el[i].damageBase;
}
SelectKing();
**UpdateAllMoves();**
}
Here is the Update Nodes Function:
public void UpdateNodes()
{
for(int i = 0; i < unitList.Count; i++)
{
for(int j = 0; j < unitList[i].possibleMoves.Length; j++)
{
for(int k = 0; k < unitList[i].possibleMoves[j].Count; k++)
{
unitList[i].possibleMoves[j][k].moveableByUnit.Add(new CheckAssist(unitList[i], j));
}
}
for (int j = 0; j < unitList[i].possibleAttacks.Length; j++)
{
for (int k = 0; k < unitList[i].possibleAttacks[j].Count; k++)
{
unitList[i].possibleAttacks[j][k].attackableByUnit.Add(new CheckAssist(unitList[i], j));
}
}
for (int j = 0; j < unitList[i].possibleAttackIndicators.Length; j++)
{
for (int k = 0; k < unitList[i].possibleAttackIndicators[j].Count; k++)
{
unitList[i].possibleAttackIndicators[j][k].attackableByUnit.Add(new CheckAssist(unitList[i], j));
}
}
for (int j = 0; j < unitList[i].possibleAttacksInactive.Length; j++)
{
for (int k = 0; k < unitList[i].possibleAttacksInactive[j].Count; k++)
{
unitList[i].possibleAttacksInactive[j][k].passiveAAByUnit.Add(new CheckAssist(unitList[i], j));
}
}
}
for (int i = 0; i < enemyList.Count; i++)
{
for (int j = 0; j < enemyList[i].possibleMoves.Length; j++)
{
for (int k = 0; k < enemyList[i].possibleMoves[j].Count; k++)
{
enemyList[i].possibleMoves[j][k].moveableByEnemy.Add(new CheckAssist(enemyList[i], j));
}
}
for (int j = 0; j < enemyList[i].possibleAttacks.Length; j++)
{
for (int k = 0; k < enemyList[i].possibleAttacks[j].Count; k++)
{
enemyList[i].possibleAttacks[j][k].attackableByEnemy.Add(new CheckAssist(enemyList[i], j));
//Debug.Log("added attack to" + enemyList[i].possibleAttackIndicators[j][k].xPos + " " + enemyList[i].possibleAttackIndicators[j][k].yPos);
}
}
for (int j = 0; j < enemyList[i].possibleAttackIndicators.Length; j++)
{
for (int k = 0; k < enemyList[i].possibleAttackIndicators[j].Count; k++)
{
enemyList[i].possibleAttackIndicators[j][k].attackableByEnemy.Add(new CheckAssist(enemyList[i], j));
//Debug.Log("added attack to" + enemyList[i].possibleAttackIndicators[j][k].xPos + " " + enemyList[i].possibleAttackIndicators[j][k].yPos);
}
}
for (int j = 0; j < enemyList[i].possibleAttacksInactive.Length; j++)
{
for (int k = 0; k < enemyList[i].possibleAttacksInactive[j].Count; k++)
{
enemyList[i].possibleAttacksInactive[j][k].passiveAAByEnemy.Add(new CheckAssist(unitList[i], j));
}
}
}
}
The problem seems to be that some line among these:
CheckforCheckUnit(grid);
CheckforCheckEnemy(grid);
ConvertAllMoves();
grid.ClearNodeMoves();
grid.UpdatePosition();
UpdateNodes();
grid.UpdatePosition();
is modifying the Units in unitList in some way that sets the Unit.grid value to null.
Something else you might consider is adding GridManager as a parameter to UpdatePosition():
public override void UpdatePosition(GridManager gameGrid) {
vecPos = GameObject.Find("WUZ(Clone)").transform.position;
Debug.Log(this + " the grid: " + gameGrid);
position = gameGrid.GetNode((int)vecPos.x, (int)vecPos.y);
}
and then in UpdateAllMoves, include it in the calls. e.g.:
...
el[i].UpdatePosition(grid);
...
ul[i].UpdatePosition(grid);
...
I fixed my own Code and here is how:
unitList.Add(StaticPara.player1Units[i].GetComponent<Unit>());
int x = startingTilesBlue[i].xPos;
int y = startingTilesBlue[i].yPos;
GenerateCharacters(x, y, StaticPara.player1Units[i], 0);
I added the Unit script from the passed the GameObject rather than the Unit script from the instantiated Gameobject meaning I changed variables that were not even in the List
Thanks for all the help #ruzihm
EDIT: Yes I did I moved unitList.Add from GettingCharacters() to GenerateCharacters()

How to get all possible 2x2 sub matrices in a 3x3 matrix in C#?

If matrix A of size (3x3), then should i use the method of finding determinants, like grabbing the rows and column of first element and removing it from the array 2D array to get the remaining elements and then moving to the next element and repeating the same steps ?
[{1,2,3},
{4,5,6},
{7,8,9}]
I finally was able to do it, here's what I did :
enter image description here
class program
{
public static void Main()
{
int[,] arr = new int[3, 3];
Console.WriteLine("Enter elements of " + (arr.GetUpperBound(0) + 1) + "x" + (arr.GetUpperBound(1) + 1) + " matrix:");
for (int i = 0; i < (arr.GetUpperBound(0) + 1); i++)
{
for (int j = 0; j < (arr.GetUpperBound(1) + 1); j++)
{
arr[i, j] = Convert.ToInt32(Console.ReadLine());
}
}
Console.WriteLine("Matrix entered: ");
for (int i = 0; i < (arr.GetUpperBound(0) + 1); i++)
{
for (int j = 0; j < (arr.GetUpperBound(1) + 1); j++)
{
Console.Write("\t" + arr[i, j]);
}
Console.WriteLine();
}
Console.WriteLine("Possible sub-matrices: ");
for (int i = 0; i < 3; i++)
{
for (int j = 0; j< 3; j++)
{
TrimArray(i,j,arr);
}
}
}
public static int[,] TrimArray(int row, int column, int[,] original)
{
int[,] resultant = new int[original.GetLength(0) - 1, original.GetLength(1) - 1];
for (int i = 0, j = 0; i < original.GetLength(0); i++)
{
if (i == row)
continue;
for (int k = 0, u = 0; k < original.GetLength(1); k++)
{
if (k == column)
continue;
resultant[j, u] = original[i, k];
u++;
}
j++;
}
Console.WriteLine();
for (int i = 0; i < 2; i++)
{
for (int j = 0; j< 2; j++)
{
Console.Write("\t"+resultant[i,j]);
}
Console.WriteLine();
}
return resultant;
}
}
I did this for you yesterday, I created a method that will return a square matrix, given a parent matrix and the length.
static void Main(string[] args)
{
int[][] parentMatrix = new int[][]
{
new int [] { 1, 2, 3 },
new int [] { 4, 5, 6 },
new int [] { 7, 8, 9 }
};
var chunks = GetSubMatrices(parentMatrix, 2);
Console.WriteLine(chunks);
}
static List<int[][]> GetSubMatrices(int[][] parentMatrix, int m)
{
int n = parentMatrix.Length > m ? parentMatrix.Length : throw new InvalidOperationException("You can't use a matrix smaller than the chunk size");
var chunks = new List<int[][]>();
int movLimit = n - m + 1;
var allCount = Math.Pow(movLimit, 2);
for (int selRow = 0; selRow < movLimit; selRow ++)
{
for (int selCol = 0; selCol < movLimit; selCol ++)
{
// this is start position of the chunk
var chunk = new int[m][];
for (int row = 0; row < m; row++)
{
chunk[row] = new int[m];
for (int col = 0; col < m; col++)
{
chunk[row][col] = parentMatrix[selRow + row][selCol + col];
}
}
chunks.Add(chunk);
}
}
return chunks;
}
If you have any problems using it, you can simply comment below.
I needed to solve a problem like and came up with this answer. Hope it adds to your library of answers. If the submatrix specified is not greater than 1, do nothing.
public static void GetSubMatrixes(int[,] arr, int size)
{
int parentMatrixRowLength = arr.GetLength(0);
int parentMatrixColLength = arr.GetLength(1);
var overall = new List<object>();
if(size > 1)
{
for (int i = 0; i < parentMatrixRowLength; i++)
{
//get the columns
for (int j = 0; j < parentMatrixColLength; j++)
{
var subMatrix = new int[size, size];
/*if the new matrix starts from second to the last value in either the row(horizontal or column)
* do not proceed, go to the row or column in the parent matrix
* */
if (j < parentMatrixColLength - (size - 1) && i < parentMatrixRowLength - (size - 1))
{
//add
for (int m = 0; m < subMatrix.GetLength(0); m++)
{
for (int n = 0; n < subMatrix.GetLength(1); n++)
{
/*check the sum of current column value and the sum of the current row value
* of the parent column length and row length if it goes out of bounds
*/
var row = i + m; var col = j + n;
//actual check here
if (row < parentMatrixRowLength && col < parentMatrixColLength)
{
subMatrix[m, n] = arr[i + m, j + n];
}
}
}
overall.Add(subMatrix);
}
}
}
//display the sub matrixes here
for (int i = 0; i < overall.Count; i++)
{
var matrix = overall[i] as int[,];
for (int y = 0; y < matrix.GetLength(0); y++)
{
for (int x = 0; x < matrix.GetLength(1); x++)
{
Console.Write(string.Format("{0} ", matrix[y, x]));
}
Console.Write(Environment.NewLine + Environment.NewLine);
}
Console.WriteLine();
}
}
}

Out of index exception

Sorry if there is a simple solution to this, been trying to figure it out for a few hours, i can't seem to find the problem to the code, what could be wrong with it?
public static void ShortestPath(int[,] waypoint, int source, int verticesCount)
{
source = 0;
waypoint = new int[verticesCount, verticesCount];
int[] distance = new int[verticesCount];
int[] previous = new int[verticesCount];
PriorityQueue<int> priorityqueue = new PriorityQueue<int>();
for (int i = 0; i < verticesCount; i++)
{
for (int l = 0; l < verticesCount; l++)
{
if (waypoint[i, l] != 0)
{
priorityqueue.Enqueue(i, waypoint[i, l]);
}
}
}
while (!priorityqueue.empty() || priorityqueue != null)
{
int o = priorityqueue.dequeue_min();
for (int v = 0; v < verticesCount; ++v)
{
previous[v] = 0;
MinimumDistance(distance, verticesCount);
if (waypoint[o, v] != 0)
{
if (distance[o] + waypoint[o, v] < distance[v])
distance[v] = distance[o] + waypoint[o, v];
previous[v] = o;
priorityqueue.Enqueue(o, distance[v]);
}
Print(distance[], verticesCount);
}
}
I believe your issue is with the if in your while loop where you are using ++v instead of v++.
Code should be:
...
for (int v = 0; v < verticesCount; v++)
...

Grid Algorithm, similar to WPF Grid

Edit
Upon further reading and experimenting my reformulated questions :
How do I measure a Star Column Contents, specially when the contents of the grid can span multiple Cols/Rows?
If I have a Control that is inside Col 0, and it spans 2 cols.
and Col 0 is a Star Col, what size would the column actually take?
Or am I missing something?
EDIT:
Since it seems I didnt explain myself well enough, what I actually need to do is find how to make each of the contents mesure themselfs and report back to the actual Col/Row. My issues is mostly, what happens when a control spans multiple rows, I might be missing something on the grid actually works.
I would like to implement a GRID similar to WPF Grid, but I am having trouble understanding how the algoritm to Mesure the Grid actually works, currently I have something like this :
protected override Size MesureOverride(Size s)
{
int colCount = Columns.Count;
int rowCount = Rows.Count;
bool emptyRows = rowCount == 0;
bool emptyCol = colCount == 0;
if (emptyRows)
rowCount = 1;
if (emptyCol)
colCount = 1;
rows = new GridSegment[rowCount];
cols = new GridSegment[colCount];
if (float.IsNaN(s.Width))
{
//We are trying to mesure our size top
//Find what our contents width is
}
if (float.IsNaN(s.Height))
{
//find what our contents height is
}
CreateCells(s, emptyRows, rows, cols, emptyCol);
float gridWidth = 0;
float gridHeight = 0;
foreach (var col in cols)
{
gridWidth += col.DesiredSize;
}
foreach (var row in rows)
{
gridHeight += row.DesiredSize;
}
float mesureHeight = 0f;
float mesureWidth = 0f;
foreach (var v in this.Childreen)
{
var layoutInfo = v.Layout<GridLayoutInfo>();
var rowspan = layoutInfo.RowSpan;
var colspan = layoutInfo.ColumSpan;
float width = 0;
float height = 0;
float x = 0;
float y = 0;
if (rowspan < 1)
rowspan = 1;
if (colspan < 1)
colspan = 0;
for (int i = 0; i < layoutInfo.Row + rowspan && i < rowCount; i++)
{
if (i > 0 && i <= layoutInfo.Row)
y += rows[i - 1].DesiredSize;
if (i >= layoutInfo.Row)
height += rows[i].DesiredSize;
}
for (int i = 0; i < layoutInfo.Column + colspan && i < colCount; i++)
{
if (i > 0 && i <= layoutInfo.Column)
x += cols[i - 1].DesiredSize;
if (i >= layoutInfo.Column)
width += cols[i].DesiredSize;
}
v.Mesure(new Size(width,height));
//Calculate the grid size
}
return new Size(gridWidth, gridHeight);
}
private void CreateCells(Size s, bool emptyRows, GridSegment[] rows, GridSegment[] cols, bool emptyCol)
{
float avaiableWith = s.Width;
float avaiableHeight = s.Height;
if (!float.IsNaN(Width))
avaiableWith = Width;
if (!float.IsNaN(Height))
avaiableHeight = Height;
float totalRowFixed = 0;
float totalColFixed = 0;
float maxStarRow = 0;
float maxStarCol = 0;
if (emptyRows)
{
rows[0] = new GridSegment(0, 0, float.PositiveInfinity, MesureType.Start);
rows[0].Stars = 1;
maxStarRow = 1;
}
else
for (int index = 0; index < Rows.Count; index++)
{
var v = Rows[index];
rows[index] = new GridSegment(0, v.Min, v.Max, v.Type);
var current = rows[index];
if (current.Type == MesureType.Fixed)
{
//our desired size in units
current.DesiredSize = Mathf.Clamp(v.Value, current.Min, current.Max);
totalRowFixed += current.DesiredSize;
}
else if (current.Type == MesureType.Start)
{
current.Stars = v.Value;
maxStarRow += current.Stars;
}
}
if (emptyCol)
{
cols[0] = new GridSegment(1, 0, float.PositiveInfinity, MesureType.Start);
cols[0].Stars = 1;
maxStarCol = 1;
}
else
for (int index = 0; index < Columns.Count; index++)
{
var v = Columns[index];
cols[index] = new GridSegment(0, v.Min, v.Max, v.Type);
var current = cols[index];
if (current.Type == MesureType.Fixed)
{
//our desired size in units
current.DesiredSize = Mathf.Clamp(v.Value, current.Min, current.Max);
totalColFixed += current.DesiredSize;
}
else if (current.Type == MesureType.Start)
{
current.Stars = v.Value;
maxStarCol += current.Stars;
}
}
//TODO::ADD THE AUTO SIZED DEFs
//Calculate the sizings for all * columns
{
var starColumns = cols.Where(x => x.Type == MesureType.Start);
var stepStarColl = (avaiableWith - totalColFixed) / maxStarCol;
foreach (var gridSegment in starColumns)
{
gridSegment.DesiredSize = stepStarColl * gridSegment.Stars;
}
var starRows = rows.Where(x => x.Type == MesureType.Start);
var stepStarRows = (avaiableHeight - totalRowFixed) / maxStarRow;
foreach (var gridSegment in starRows)
{
gridSegment.DesiredSize = stepStarRows * gridSegment.Stars;
}
}
}
protected override Size ArrangeOverride(Size s)
{
int colCount = Columns.Count;
int rowCount = Rows.Count;
bool emptyRows = rowCount == 0;
bool emptyCol = colCount == 0;
if (emptyRows)
rowCount = 1;
if (emptyCol)
colCount = 1;
rows = new GridSegment[rowCount];
cols = new GridSegment[colCount];
CreateCells(s, emptyRows, rows, cols, emptyCol);
////Loop through all controls
foreach (var v in this.Childreen)
{
var layoutInfo = v.Layout<GridLayoutInfo>();
var rowspan = layoutInfo.RowSpan;
var colspan = layoutInfo.ColumSpan;
float width = 0;
float height = 0;
float x = 0;
float y = 0;
if (rowspan < 1)
rowspan = 1;
if (colspan < 1)
colspan = 0;
for (int i = 0; i < layoutInfo.Row + rowspan && i < rowCount; i++)
{
if (i > 0 && i <= layoutInfo.Row)
y += rows[i - 1].DesiredSize;
if ( i>= layoutInfo.Row )
height += rows[i].DesiredSize;
}
for (int i = 0; i < layoutInfo.Column + colspan && i < colCount; i++)
{
if (i > 0 && i <= layoutInfo.Column)
x += cols[i - 1].DesiredSize;
if (i >= layoutInfo.Column)
width += cols[i].DesiredSize;
}
v.Arrange(new Rect(x, y, width, height));
}
float gridWidth = 0;
float gridHeight = 0;
foreach (var col in cols)
{
gridWidth += col.DesiredSize;
}
foreach (var row in rows)
{
gridHeight += row.DesiredSize;
}
return new Size(gridWidth, gridHeight);
}
This is from my custom library, but I tried to keep it as close to WPF syntax as possible.
This code works almost as I want, but fails once the grid is inside a ScrollingContainer, since the size passed to the measure is Infinity, and it makes the grid take on a infinity large size.
Does anyone have an idea on how to solve this, I am not even using Auto Cols/Rows, since I thought it would simplify the Alg alot - I dwelled into the source of WPF, but I have major hard time trying to understand how it works.

Categories