Unity Dynamically Limiting a Slider in a Custom Editor Panel - c#

I have attempted this in my panel already by working out the remaining amount of the total percentage and setting that as top limit of slider but that either seems to be inaccurate because my logic is wrong or it breaks the panel.
Currently the panel is scripted as shown below with the maximum the sliders can reach is 10 with a label showing me the total so i dont go over which is highly impractical.
public static int ammoxBoxesPercent = EditorPrefs.GetInt("Ammo");
public static int medicKitsPercent = EditorPrefs.GetInt("MedicKits");
public static int amountOfItemsPerZone = EditorPrefs.GetInt("Amount");
public static int totalPercentageVal;
public static int maxTotalValue = 10;
[MenuItem("Enviroment Controls/ Object Spawners Control Panel")]
private static void showEditor()
{
EditorWindow.GetWindow<ObjectSpawnersControlPanel>(false, "OBJ Spawners CP");
}
void OnGUI()
{
ammoxBoxesPercent = EditorGUILayout.IntSlider("Ammox Box Percent", ammoxBoxesPercent, 1, 10);
EditorPrefs.SetInt("Ammo", ammoxBoxesPercent);
medicKitsPercent = EditorGUILayout.IntSlider("Medic Kit Percent", medicKitsPercent, 1, 10);
EditorPrefs.SetInt("MedicKits", medicKitsPercent);
amountOfItemsPerZone = EditorGUILayout.IntSlider("Amount of Items Spawned at Each Zone", amountOfItemsPerZone, 1, 5);
EditorPrefs.SetInt("Amount", amountOfItemsPerZone);
totalPercentageVal = medicKitsPercent + ammoxBoxesPercent;
EditorGUILayout.LabelField ("Total Percentage so far : " + totalPercentageVal.ToString() + "0");
EditorGUILayout.LabelField ("Total must not go above 100");
}
The goal is to have it so when i set the first slider to say 6 i then set the limit of second slider to 4 because the percentage limit is 10 (representing 100 percent in my case)
Anybody know i decent method to achieve this?

Fairly easy. Just calculate 10 - ammoxBoxesPercent and use that as the max value for your IntSlider for medicKitsPercent.
One thing you'd want to do is to set the lower limit for medicKitsPercent to 0, so in case you hit 10 on ammoxBoxesPercent (Since you want the total to be 10 at max)
medicKitsPercent = EditorGUILayout.IntSlider("Medic Kit Percent", medicKitsPercent, 0, maxTotalValue - ammoxBoxesPercent);

Related

How can I make a variable independent of the values ​assigned to it? Unity c#

I'm trying to make a game in unity an Idle/Clicker type game.
public long m_Amount;
public int multiplier=1;
void Update()
{
m_Amount_click = GetComponent<ButtonMoney>().m_Amount_click1;
m_Amount_click=m_Amount_click*multiplier;
m_Amount = m_Amount_click;
Moneys.text= "$" + m_Amount.ToString("##,##0");
}
I want m_Amount to be set at that value and not be influenced by the multiplier when it gets increased or by m_Amount_Click when it gets reset when the game restarts/exit.
I'm trying to set the value of m_amount and not be depedent of m_amount_click and multiplier.
Example:
If I increase the multiplier by 1, the value on m_amount_click will be =2 but the m_amount won't change from 1000 to 2000 when i do that.

Oxyplot - edit the left-click label in a LineSeries

I'm plotting a few different LineSeries in Oxyplot (in C#, using Windows Forms), which all have wildly different ranges. To make every series still visible, I'm scaling all their values to the range from 0 to 1. Of course the problem here is, that the actual values of the series can't be displayed anymore, so I wondered if it's possible to change the left-click event that displays the X and Y value of a DataPoint to fix this. If possible, I'd like it so that when the user clicks on a datapoint, the displayed Y-value would be scaled back to the original, while the graph remains scaled down.
For example, I have a Na+ value ranging from 130 to 150, which I then scale to 0 and 1. But when the user clicks on a Datapoint, I want it to display Y = 140 and not 0.5. Since every LineSeries has a different scaling factor, this would also mean that I'd have to edit the label for each series seperately.
So yeah, is something like that possible in the current version? Thanks in advance!
Edit: I figured it out, see my answer below!
I'm not sure if I'm supposed to answer my own question, but I ended up figuring it out. So anyway, it turns out I can't access any of the properties needed, so I just made my own class for the Datapoints and included a property for the scaled value. It turns out that the Tracker is capable of displaying other properties of the Datapoints, but the standard Datapoints only has X and Y. Then I modified the TrackerFormatString to show the scaled value instead of the actual one.
public class MeasurePoint : IDataPointProvider
{
public MeasurePoint(double x, double y, double scale)
{
X = x; Y = y; Scale = scale;
}
public double X { get; set; }
public double Y { get; set; }
public double Scale { get; set; }
public DataPoint GetDataPoint()
{
return new DataPoint(X, Y);
}
}
That is the class I created and this is how I ended up handling the points.
var points = new MeasurePoint[Y.Count - 1];
for (int i = 0; i < Y.Count; i++)
{
points[i] = new MeasurePoint(DateTimeAxis.ToDouble(X[i]), Y[i], Y[i]*scale);
}
Series.ItemsSource = points;
Series.TrackerFormatString = "{0}\n{2}\n{Scale}";
scale here is the factor that I divide the values with before plotting and the TrackerFormatString is {0} the Series name and {2} is the X value.
Works pretty great!
You can't directly change the displayed data, however you can listen to the mousedown event within the oxyplot like this:
var model= new PlotModel();
model.MouseDown += Model_MouseDown;
private void Model_MouseDown(object sender, OxyMouseDownEventArgs e)
{
var controller = sender as PlotController;
var position = e.HitTestResult;
}
With the values of position you can calculate back to the actual value and display it somewhere else.

Formula for Calculating a Final Score

I'm stuck on one final piece of a calculation puzzle below. I know how to generate a percentage score of correct parts from total correct possible parts ((correctNumPartsOnBoard / totalPossibleCorrectParts)*100) but I want to the final percentage score to factor in the number the incorrect parts on the board as well. (even if all the right parts are on the board you still won't get 100% if there are also incorrect parts). Right now my current formula percentCorrectParts = ((correctNumPartsOnBoard / totalPossibleCorrectParts) / totalNumPartsOnBoard) * 100); is wrong and I'm having trouble pinpointing the correct calculation.
So, the way the calc would need to work is: a user needs to match one of the six possible animals, each animal has around 15 correct parts, but users can also drag incorrect parts onto the board (parts from the other animals are still visible so they could drag a different set of legs or horns on a lizard head, they could make frankenstein type creatures as well this way). So the total number of parts available would be 6*15. But seeing as how they're not all correct they would influence the score as well by bringing the overall score average of pieces on the board down.
What's the correct formula for this?
// Scoring System
using UnityEngine;
using System.Linq;
using System.Collections.Generic;
public class ScoreManager : MonoBehaviour
{
public List<string> totalBuildBoardParts; // Running list of all parts on board (by Tag)
public int numCorrectPartsOnBoard;
public int numIncorrectPartsOnBoard;
public int totalPossibleCorrectParts;
public float percentCorrectParts;
void Start()
{
GameObject gameController = GameObject.FindGameObjectWithTag("gc");
GameSetup gameSetup = gameController.GetComponent<GameSetup>();
totalPossibleCorrectParts = gameSetup.totalPossibleCorrectParts;
Debug.Log("TOTAL POSSIBLE CORRECT PARTS ARE: " + totalPossibleCorrectParts);
}
public void AddAnimalPartByTag(string tag)
{
// Add object tag to List
totalBuildBoardParts.Add(tag);
Debug.Log ("Added an object tagged as: " + tag);
GameObject gameController = GameObject.FindGameObjectWithTag("gc");
GameSetup gameSetup = gameController.GetComponent<GameSetup>();
if (tag == gameSetup.activeTag)
{
numCorrectPartsOnBoard ++;
Debug.Log ("There are " + numCorrectPartsOnBoard + " correct parts on the board");
} else {
numIncorrectPartsOnBoard ++;
}
CalculateScore();
}
public void RemoveAnimalPartByTag(string tag)
{
// Add object tag to List
totalBuildBoardParts.Remove(tag);
Debug.Log ("Removed an object tagged as: " + tag);
GameObject gameController = GameObject.FindGameObjectWithTag("gc");
GameSetup gameSetup = gameController.GetComponent<GameSetup>();
if (tag == gameSetup.activeTag)
{
numCorrectPartsOnBoard --;
Debug.Log ("There are " + numCorrectPartsOnBoard + " correct parts on the board");
} else {
numIncorrectPartsOnBoard --;
}
CalculateScore();
}
public void CalculateScore()
{
float totalNumPartsOnBoard = totalBuildBoardParts.Count();
float correctNumPartsOnBoard = numCorrectPartsOnBoard;
percentCorrectParts = ((correctNumPartsOnBoard / totalPossibleCorrectParts) / totalNumPartsOnBoard) * 100);
Debug.Log ("Your current score is: " + percentCorrectParts);
}
}
Your formula is probably correct. However, your datatypes are not.
You are currently doing an integer division, which results in an int too. So let's say that correctNumPartsOnBoard is 3 and totalPossibleCorrectParts is 5, 3/5 gives 0 because an int does not have any decimals.
You need to cast one of the two operands in the division as a datatype with decimals ( float, double or decimal for example):
percentCorrectParts = ((correctNumPartsOnBoard / (float)totalPossibleCorrectParts) / totalNumPartsOnBoard) * 100);
By setting denominator totalPossibleCorrectParts as a float, the first division will return a float. That float is then used in the second division, also returning correctly a float.
I think your formula should look like this:
int correctParts;
int possibleCorrect;
int incorrectParts;
int parts;
float percentFinished =
Mathf.Max((((float)correctParts/possibleCorrect) // Correct percent
- ((float)incorrectParts/parts)) // Minus incorrect percent
* 100f, // Normalized to 100
0f); // Always a minimum of 0
Also with this formula unlike other answers, you don't have to use all of the parts to get 100%, just get the total possible correct parts which doesn't necessarily have to use up all of your parts ;)
Scenario
Lets say you have 100 parts, with 3 right and 3 wrong. Total right we are aiming for here is 20.
int correctParts = 3;
int possibleCorrect = 20;
int incorrectParts = 3;
int parts = 100;
float percentFinished =
Mathf.Max((((float)correctParts/possibleCorrect) // Correct percent is 0.15 or 15%
- ((float)incorrectParts/parts)) // Minus incorrect percent which is .03 or 3%
* 100f, // Normalized to 100 which gives us 15% - 3% = 12%
0f); // Always a minimum of 0
I think your final (%age) score should be:
correctNumPartsOnBoard / totalNumPartsOnBoard * 100
If you have 80 correctparts and 20 incorrect then the total parts is 100 and you've got 80 of them correct so you should score 80% like this:
80 / (80+20) * 100

Percent of Value graph in DevExpress Grid Cell

I need to represent a percent of value as a graph in DevExpress grid cell. I am able to paint using DrawLine but my problem is as soon as the percent value is equal to greater than 1 it is treated as 100% in this code. Please find the code below, As shown in the screenshot, 3.59 should be shown less than 8.35! Please help.
private void CustomDrawCell(object sender, RowCellCustomDrawEventArgs args)
{
args.Appearance.DrawBackground(args.Graphics, args.Cache, args.Bounds);
if (column != null)
{
int penSize = args.Bounds.Height * 2 / 3;
double value = GetValue(); // This is the value against which I have to display the graph, its in %.
int left = args.Bounds.Left;
int middle = args.Bounds.Height / 2 + args.Bounds.Top;
int width = args.Bounds.Width;
int right = (int)(left + width * value);
args.Graphics.DrawLine(new Pen(Color.Green, penSize), left, middle, right, middle);
}
args.Handled = true;
}
int right = (int)(left + width * value);
This code calculates the bar length correctly only if the value is between 0 and 1. If values are between 0 and 100 or between 0 and 10, you need to divide the result of multiplying by 100 or 10 correspondingly.
int right = (int)(left + width * value / 100);
By the way, it is not necessary to puzzle over custom drawing, because you are using XtraGrid. There is the RepositoryItemProgressBar component, which can be embedded into XtraGrid cell. It displays the line according to the cell value and allows you to define the maximum and minimum value, so that the line is most exactly visualize the cell value. Read this article to learn how to assign editors to columns: Assigning Editors to Columns and Card Fields

Invert windows forms vertical scrollbar

I'm making a winforms app c#. The vertical scroll bar min value is at the top and max at the bottom, and scrolling down increases the value and vice versa. Is there a way to invert it, so that up is higher and down is lower.
You cannot actually "see" the value of the scroll bar just by looking at it, so, in other words, there is no actual difference between having min at the top, max at the bottom, and then just inverting the value when you access it:
private void ScrollBar_Scroll(object sender, ScrollEventArgs e)
{
// get the value (0 -> 100)
int value = scrollBar.Value;
// invert it (100 -> 0)
value = 100 - value;
// display it
someLabel.Text = value.ToString();
}
Of course, you can also override the VScrollBar class and add your own "inverted value" property:
public class InvertedScrollBar : VScrollBar
{
/// <summary>
/// Gets or sets the "inverted" scrollbar value.
/// </summary>
/// <value>The inverted value.</value>
public int InvertedValue
{
get
{
int offset = this.Value - this.Minimum;
return this.Maximum - offset;
}
set
{
int offset = this.Maximum - value;
this.Value = this.Minimum + offset;
}
}
}
Note that Maximum still has to be larger than Minimum when configuring it.
The values returned by the Value property of a ScrollBar go from scrollBar.Minimum to scrollBar.Maximum - scrollBar.LargeChange.
Thus if a scroll bar has Minimum of 5, Maximum of 15, and LargeChange (which doubles as the visible portion of the scrolling range) is 3, then the possible return values go from 5 to 12.
So, to invert the value, you actually want to use:
scrollBar.Minimum + scrollBar.Maximum - scrollBar.LargeChange - scrollBar.Value
(Normally you can think of Value as position of the left or top edge of the thumb. The formula above will give you the bottom edge of the thumb. If you still want the top edge (i.e. values going from 8 to 15 in the example above), then use:
scrollBar.Minimum + scrollBar.Maximum - scrollBar.Value

Categories

Resources