I am trying to display a list, generated dinamically. I created a prefab with the things I need in it (a TextView, 3 TMP_InputFields and 2 Buttons.)
To manage the different list items, I created a script (SkillManager, since the items represents skill the player can choose), which I attached to the prefab.
Then, I add every item (currently I am adding only one for testing purposes) to a List, iterate that list, and add the prefab to the Content of a ScrollView:
for(int i = 0; i < listaSkills.Count; i++)
{
GameObject listItem = Instantiate(SkillPrefab) as GameObject;
listItem.GetComponent<SkillManager>().skill = listaSkills[i];
//listItem.transform.SetParent(SkillsContent.transform, false);
listItem.transform.parent = SkillsContent.transform;
}
When I run this, no item is seen in the ScrollView, but I can see the SkillItem added to the hierarchy:
If I move to Scene tab after playing, I see a square with red lines crossing it:
Why is my item not displaying? Why the red cross? How can I populate my ScrollView?
EDIT:
This is the code of SkillManager, the script added to SkillPrefab:
public class SkillManager : MonoBehaviour
{
public TMP_InputField toSpend;
public TMP_InputField rangos;
public TMP_InputField modificadores;
public TMP_InputField total;
public Button plusButton;
public Button minusButton;
public TMP_Text nombre;
public Skill skill;
private int modificador;
private int pointsToSpend;
private int totalPoints;
// Start is called before the first frame update
void Start()
{
print("Start");
if(total!=null)
total.text = "0";
if(modificadores!=null)
modificadores.text = "0";
if (toSpend != null)
{
toSpend.GetComponent<TMP_InputField>().text = GetSkillPoints();
totalPoints = int.Parse(total.GetComponent<TMP_InputField>().text);
pointsToSpend = int.Parse(toSpend.GetComponent<TMP_InputField>().text);
}
else
{
GameObject GameObjectToSpend = GameObject.FindGameObjectWithTag("tospend");
toSpend = GameObjectToSpend.GetComponent<TMP_InputField>();
if (toSpend == null)
{
print("Sigue siendo nulo");
}
else
{
toSpend.text= GetSkillPoints();
//totalPoints = int.Parse(total.GetComponent<TMP_InputField>().text);
if(total!=null)
totalPoints = int.Parse(total.text);
if(toSpend!=null)
pointsToSpend = int.Parse(toSpend.text);
}
}
if (skill != null)
{
modificador = GetModificador(skill);
string sModificador = modificadores.GetComponent<TMP_InputField>().text;
int iModificador = int.Parse(sModificador);
modificadores.GetComponent<TMP_InputField>().text = iModificador.ToString();
}
if (plusButton != null)
{
plusButton.onClick.AddListener(PlusButtonClicked);
minusButton.onClick.AddListener(MinusButtonClicked);
}
}
private string GetSkillPoints()
{
return "1";
}
public void MinusButtonClicked()
{
string ranks = rangos.GetComponent<TMP_InputField>().text;
int ranksInt = int.Parse(ranks);
if (ranksInt > 0)
{
int newRank = ranksInt - 1;
pointsToSpend += 1;
rangos.GetComponent<TMP_InputField>().text = newRank.ToString();
toSpend.GetComponent<TMP_InputField>().text = pointsToSpend.ToString();
total.GetComponent<TMP_InputField>().text = (newRank + modificador).ToString();
skill.Puntos = newRank;
}
}
public void PlusButtonClicked()
{
string ranks=rangos.GetComponent<TMP_InputField>().text;
int ranksInt = int.Parse(ranks);
Character character = Almacen.instance.Character;
int level = character.CharacterLevel;
if (ranksInt < level && pointsToSpend > 0)
{
int newRank = ranksInt + 1;
rangos.GetComponent<TMP_InputField>().text = newRank.ToString();
pointsToSpend -= 1;
toSpend.GetComponent<TMP_InputField>().text = pointsToSpend.ToString();
total.GetComponent<TMP_InputField>().text = (newRank + modificador).ToString();
skill.Puntos = newRank;
}
}
private int GetModificador(Skill skill)
{
int retorno=0;
if (skill.Clasea)
{
retorno += 3;
}
else
{
retorno += 0;
}
retorno += GetModificadorCaracteristica();
return retorno;
}
private int GetModificadorCaracteristica()
{
Utils utils = new Utils();
int retorno = 0;
int characteristic=0;
switch (skill.Caracteristica)
{
case "Fue":
characteristic = Almacen.instance.Character.EffectiveStr;
break;
case "Des":
characteristic = Almacen.instance.Character.EffectiveDex;
break;
case "Con":
characteristic = Almacen.instance.Character.EffectiveCon;
break;
case "Int":
characteristic = Almacen.instance.Character.EffectiveInt;
break;
case "Sab":
characteristic = Almacen.instance.Character.EffectiveWis;
break;
case "Car":
characteristic = Almacen.instance.Character.EffectiveCha;
break;
}
retorno = utils.GetCharModifier(characteristic);
return retorno;
}
}
it looks like you instantiate the object as a GameObject. but this will not be seen in the canvas because it isn't a UI component. you may want to add a sprite or image to the component and instantiate that into the Canvas. it will look something like this:
public class SkillPrefab
{
//put all your variables here!!!
public Sprite skillSprite;
}
public class YourClassName : MonoBehaviour
{
[SerializeField]
public List<SkillPrefab> skills = new List<SkillPrefab>();
private void Update()
{
Sprite listItem = Instantiate(skills[0].skillSprite); //the index is the skill you want to spawn in the list.
}
}
this does take into account that you have made your skills into a list of skills that you can acces.
Unity C#
I made a list. The color changes after 5 seconds. I defined the color from which the list begins ("_currentIndex = 0"). The first color should always be the one I defined at the beginning. What I have means that each color on the list is selected one by one. After the last color everything comes back to the beginning.
I would like the first color to always be the same, but each subsequent one was chosen randomly from the list. It must be an infinite loop.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ColorCycler : MonoBehaviour
{
public Color[] Colors;
public float Speed = 5;
int _currentIndex;
Camera _cam;
bool _shouldChange = false;
private int randomColors;
void Start()
{
_cam = GetComponent<Camera>();
_currentIndex = 0;
SetColor(Colors[_currentIndex]);
}
public void SetColor(Color color)
{
_cam.backgroundColor = color;
}
public void Cycle()
{
_shouldChange = true;
}
void Update()
{
if (_shouldChange)
{
var startColor = _cam.backgroundColor;
//start from color with number
var endColor = Colors[0];
if (_currentIndex + 1 < Colors.Length)
{
endColor = Colors[_currentIndex + 1];
}
var newColor = Color.Lerp(startColor, endColor, Time.deltaTime * Speed);
SetColor(newColor);
if (newColor == endColor)
{
_shouldChange = false;
if (_currentIndex + 1 < Colors.Length)
{
_currentIndex++;
}
else
{
_currentIndex = 0;
}
}
}
}
}
If you just want a random element from a list then just choose a random index.
Random random = new Random();
int randomIndex = random.Next(Colors.Count);
color = Colors[randomIndex];
Hello programmers all around the world. I have made myself an inventory system for my game. Only problem is that when I click on item and then drag it to and empty slot it doesn't move and I kinda don't see the error which I am having and I have tried to debug it but without success any help? Here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class Inventory : MonoBehaviour {
private RectTransform inventoryRect;
private float inventoryWidth;
private float inventoryHeight;
public int slots;
public int rows;
public float slotPaddingLeft;
public float slotPaddingTop;
public float slotSize;
public GameObject slotPrefab;
private static Slot from;
private static Slot to;
private List<GameObject> allslots;
public GameObject iconPrefab;
private static GameObject hoverObject;
private static int emptySlots;
public Canvas canvas;
private float hoverYOffset;
private bool isPressed;
public EventSystem eventSystem;
public static int EmptySlots{
get{ return emptySlots;}
set{ emptySlots = value;}
}
// Use this for initialization
void Start () {
CreateLayout ();
canvas.enabled = false;
isPressed = false;
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown (KeyCode.I)) {
if (Input.GetKeyDown (KeyCode.I)) {
canvas.enabled = false;
}
canvas.enabled = true;
}
if (Input.GetMouseButtonUp (0)) {
if (!eventSystem.IsPointerOverGameObject (-1) && from != null) {
from.GetComponent<Image> ().color = Color.white;
from.ClearSlot ();
Destroy (GameObject.Find ("Hover"));
to = null;
from = null;
hoverObject = null;
}
}
if (hoverObject != null) {
Vector2 position;
RectTransformUtility.ScreenPointToLocalPointInRectangle (canvas.transform as RectTransform, Input.mousePosition, canvas.worldCamera, out position);
position.Set (position.x, position.y - hoverYOffset);
hoverObject.transform.position = canvas.transform.TransformPoint (position);
}
}
private void CreateLayout(){
allslots = new List<GameObject> ();
hoverYOffset = slotSize * 0.01f;
emptySlots = slots;
inventoryWidth = (slots / rows) * (slotSize + slotPaddingLeft) + slotPaddingLeft;
inventoryHeight = rows * (slotSize + slotPaddingTop) + slotPaddingTop;
inventoryRect = GetComponent<RectTransform> ();
inventoryRect.SetSizeWithCurrentAnchors (RectTransform.Axis.Horizontal, inventoryWidth);
inventoryRect.SetSizeWithCurrentAnchors (RectTransform.Axis.Vertical, inventoryHeight);
int colums = slots / rows;
for (int y = 0; y < rows; y++) {
for (int x = 0; x < colums; x++) {
GameObject newSlot = (GameObject)Instantiate (slotPrefab);
RectTransform slotRect = newSlot.GetComponent<RectTransform> ();
newSlot.name = "Slot";
newSlot.transform.SetParent (this.transform.parent);
slotRect.localPosition = inventoryRect.localPosition + new Vector3 (slotPaddingLeft * (x + 1) + (slotSize * x), -slotPaddingTop * (y + 1) - (slotSize * y));
slotRect.SetSizeWithCurrentAnchors (RectTransform.Axis.Horizontal, slotSize);
slotRect.SetSizeWithCurrentAnchors (RectTransform.Axis.Vertical, slotSize);
allslots.Add (newSlot);
}
}
}
public bool AddItem(Item item){
if (item.maxSize == 1) {
PlaceEmpty (item);
return true;
}
else {
foreach (GameObject slot in allslots) {
Slot temporary = slot.GetComponent<Slot> ();
if (!temporary.IsEmpty) {
if (temporary.CurrentItem.type == item.type && temporary.IsAvailable) {
temporary.AddItem (item);
return true;
}
}
}
if (emptySlots > 0) {
PlaceEmpty (item);
}
}
return false;
}
private bool PlaceEmpty(Item item){
if (emptySlots > 0) {
foreach (GameObject slot in allslots) {
Slot temporary = slot.GetComponent<Slot> ();
if (temporary.IsEmpty) {
temporary.AddItem (item);
emptySlots--;
return true;
}
}
}
return false;
}
public void MoveItem(GameObject clicked){
if (from == null) {
if (!clicked.GetComponent<Slot> ().IsEmpty) {
from = clicked.GetComponent<Slot> ();
from.GetComponent<Image> ().color = Color.gray;
hoverObject = (GameObject)Instantiate (iconPrefab);
hoverObject.GetComponent<Image> ().sprite = clicked.GetComponent<Image> ().sprite;
hoverObject.name = "Hover";
RectTransform hoverTransform = hoverObject.GetComponent<RectTransform> ();
RectTransform clickedTransform = clicked.GetComponent<RectTransform> ();
hoverTransform.SetSizeWithCurrentAnchors (RectTransform.Axis.Horizontal, clickedTransform.sizeDelta.x);
hoverTransform.SetSizeWithCurrentAnchors (RectTransform.Axis.Vertical, clickedTransform.sizeDelta.y);
hoverObject.transform.SetParent (GameObject.Find ("Canvas").transform, true);
hoverObject.transform.localScale = from.gameObject.transform.localScale;
}
}
else if (to = null) {
to = clicked.GetComponent<Slot> ();
Destroy (GameObject.Find ("Hover"));
}
if (to != null && from != null) {
Stack<Item> tmpTo = new Stack<Item> (to.Items);
to.AddItems (from.Items);
if (tmpTo.Count == 0) {
from.ClearSlot ();
}
else {
from.AddItems (tmpTo);
}
from.GetComponent<Image> ().color = Color.white;
to = null;
from = null;
hoverObject = null;
}
}
}
The method which is causing the problem is the MoveItem() sadly it is not a nullreference or nullpointer and I simply am out of ideas been strugling with it for a couple of days... Any advice on how to fix this would be helpfull and much welcomed indeed. Thanks in advance!
I haven't taken a long look at your code but right away I saw this issue:
else if (to = null) {
to = clicked.GetComponent<Slot> ();
Destroy (GameObject.Find ("Hover"));
}
This is causing the end location to be set to null. To fix this, change to double equals like so:
else if (to == null) {
to = clicked.GetComponent<Slot> ();
Destroy (GameObject.Find ("Hover"));
}
If this does not solve your problem, let me know and I'll look at your code harder.
I am trying to store the count of number of times an item from a list view is clicked in a custom array list but in my code the quantity of only the first clicked item is increasing and if i click on any other item then it gets added to the list view instead of increasing the quantity. Please tell me if you know any other method to get the count. Thanks
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Flowers item = (Flowers) parent.getAdapter().getItem(position);
if(item == null)
{
Toast.makeText(getBaseContext(),"item is null",Toast.LENGTH_LONG).show();
}else {
selectedItems items = new selectedItems();
items.setName(item.getName());
items.setCategory(item.getCategory());
Counter counter = new Counter();
if(selectedItemsArrayList.isEmpty())
{
counter.CartItemPosition = 0;
counter.MenuItemPosition = position;
counter.quantity = 1;
items.setQuantity(counter.quantity);
count.add(counter);
selectedItemsArrayList.add(items);
}
else
{
for(Counter c : count)
{
if(c.MenuItemPosition == position)
{
c.quantity = c.quantity + 1;
int i = c.CartItemPosition;
selectedItemsArrayList.get(i).setQuantity(c.quantity);
break;
}
else
{
Counter obj = new Counter();
obj.MenuItemPosition = position;
obj.CartItemPosition++;
obj.quantity=1;
count.add(obj);
items.setQuantity(obj.quantity);
selectedItemsArrayList.add(items);
return;
}
}
}
}
}
});
and my Counter class is
public class Counter {
public int CartItemPosition;
public int MenuItemPosition;
public int quantity;}
I am trying to create a PDF based on some vector art I have in my C# application. I have two major problems when I try to map the points and types from a GraphicsPath.
Some paths are just plain missing.
When a sub path is an internal boundary I need to indicate that somehow. ie, the circle in the letter d is filled in.
I'm referencing iTextSharp 5.5.2 on NuGet. I'm only using AddString here because I want an easy way to demonstrate creating a complex path in this example. For my need I won't be using a path to place text in the PDF.
using iTextSharp.text;
using iTextSharp.text.pdf;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PdfGen
{
class StackQuestion
{
public static void Main()
{
string filename = #"d:\itext.pdf";
using (var doc = new Document())
using (var fs = new FileStream(filename, FileMode.Create))
{
var writer = PdfWriter.GetInstance(doc, fs);
doc.Open();
writer.DirectContent.SetColorFill(BaseColor.BLACK);
var path = new GraphicsPath(FillMode.Winding);
path.AddString("Hello World", FontFamily.GenericSerif,
(int)FontStyle.Regular, 25f, RectangleF.Empty,
StringFormat.GenericDefault);
AddPath(path, writer.DirectContent);
doc.Close();
}
System.Diagnostics.Process.Start(filename);
}
static void AddPath(GraphicsPath path, PdfContentByte to)
{
var view = to.PdfDocument.PageSize;
path.FillMode = System.Drawing.Drawing2D.FillMode.Winding;
var d = path.PathData;
for (int i = 0; i < d.Points.Length && i < d.Types.Length; i++)
{
var t = (PathPointType)d.Types[i];
var p = Fix(d.Points[i], view);
if (Match(t, PathPointType.Bezier))
{
var p2 = Fix(d.Points[++i], view);
if (d.Types.Length > i + 1 &&
Match((PathPointType)d.Types[i + 1],
PathPointType.Bezier3))
{
var p3 = Fix(d.Points[++i], view);
to.CurveTo(p.X, p.Y, p2.X, p2.Y, p3.X, p3.Y);
}
else
{
to.CurveTo(p.X, p.Y, p2.X, p2.Y);
}
}
if (Match(t, PathPointType.Line))
{
to.LineTo(p.X, p.Y);
}
if (Match(t, PathPointType.CloseSubpath))
{
to.ClosePath();
to.EoFill();
}
if (t == PathPointType.Start)
{
to.NewPath();
to.MoveTo(p.X, p.Y);
}
}
}
static bool Match(PathPointType type, PathPointType match)
{
return (type & match) == match;
}
static System.Drawing.PointF Fix(System.Drawing.PointF pt,
iTextSharp.text.Rectangle view)
{
return new System.Drawing.PointF(pt.X, view.Height - pt.Y);
}
}
}
I'm posting an answer to myself in case anyone else is in need of a simple function to plot out a GraphicsPath in iTextSharp. I had two problems with my sample code in the question:
as mkl pointed out I was trying to fill too often
I failed to notice that PathPointType.Line is a valid mask in PathPointType.Bezier so the code placing a line back to the origin after a curve.
Updatd Code:
using iTextSharp.text;
using iTextSharp.text.pdf;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
namespace PdfGen
{
class StackQuestion
{
public static void Main()
{
string filename = #"d:\itext.pdf";
using (var doc = new Document())
using (var fs = new FileStream(filename, FileMode.Create))
{
var writer = PdfWriter.GetInstance(doc, fs);
doc.Open();
writer.DirectContent.SetColorFill(BaseColor.BLACK);
var path = new GraphicsPath(FillMode.Winding);
path.AddString("Hello World", FontFamily.GenericSansSerif,
(int)FontStyle.Regular, 90f, PointF.Empty,
StringFormat.GenericDefault);
AddPath(path, writer.DirectContent);
writer.DirectContent.EoFill();
doc.Close();
}
System.Diagnostics.Process.Start(filename);
}
static void AddPath(GraphicsPath path, PdfContentByte to)
{
var view = to.PdfDocument.PageSize;
var d = path.PathData;
to.NewPath();
PointF? start = null;
for (int i = 0; i < d.Points.Length && i < d.Types.Length; i++)
{
var t = (PathPointType)d.Types[i];
var p = Fix(d.Points[i], view);
if (Match(t, PathPointType.Bezier))
{
var p2 = Fix(d.Points[++i], view);
if (d.Types.Length > i + 1 &&
Match((PathPointType)d.Types[i + 1],
PathPointType.Bezier))
{
var p3 = Fix(d.Points[++i], view);
to.CurveTo(p.X, p.Y, p2.X, p2.Y, p3.X, p3.Y);
}
else
{
to.CurveTo(p.X, p.Y, p2.X, p2.Y);
}
}
else if (Match(t, PathPointType.Line))
{
to.LineTo(p.X, p.Y);
}
if (Match(t, PathPointType.CloseSubpath))
{
if (start != null)
to.LineTo(start.Value.X, start.Value.Y);
start = null;
to.ClosePath();
}
if (t == PathPointType.Start)
{
if (start != null)
to.LineTo(start.Value.X, start.Value.Y);
start = p;
to.MoveTo(p.X, p.Y);
}
}
}
static bool Match(PathPointType type, PathPointType match)
{
return (type & match) == match;
}
static System.Drawing.PointF Fix(System.Drawing.PointF pt,
iTextSharp.text.Rectangle view)
{
return new System.Drawing.PointF(pt.X, view.Height - pt.Y);
}
}
}