382 lines
13 KiB
C#
382 lines
13 KiB
C#
|
|
using System.Collections.Generic;
|
||
|
|
using UnityEngine;
|
||
|
|
using UnityEngine.UI;
|
||
|
|
|
||
|
|
public class CraftingUI : MonoBehaviour
|
||
|
|
{
|
||
|
|
public CraftingSystem craftingSystem;
|
||
|
|
public Inventory inventory;
|
||
|
|
public Transform recipeContainer;
|
||
|
|
public GameObject recipeButtonPrefab;
|
||
|
|
public Text messageText;
|
||
|
|
public Text selectedRecipeText;
|
||
|
|
public Font uiFont;
|
||
|
|
|
||
|
|
private readonly List<GameObject> recipeButtons = new List<GameObject>();
|
||
|
|
private RecipeData selectedRecipe;
|
||
|
|
|
||
|
|
private void OnEnable()
|
||
|
|
{
|
||
|
|
if (craftingSystem != null)
|
||
|
|
{
|
||
|
|
craftingSystem.OnCraftingChanged += RefreshRecipeButtons;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (inventory != null)
|
||
|
|
{
|
||
|
|
inventory.OnInventoryChanged += RefreshRecipeButtons;
|
||
|
|
}
|
||
|
|
|
||
|
|
BuildRecipeList();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void OnDisable()
|
||
|
|
{
|
||
|
|
if (craftingSystem != null)
|
||
|
|
{
|
||
|
|
craftingSystem.OnCraftingChanged -= RefreshRecipeButtons;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (inventory != null)
|
||
|
|
{
|
||
|
|
inventory.OnInventoryChanged -= RefreshRecipeButtons;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void BuildRecipeList()
|
||
|
|
{
|
||
|
|
ClearRecipeButtons();
|
||
|
|
|
||
|
|
if (craftingSystem == null || recipeContainer == null || recipeButtonPrefab == null)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
ConfigureRecipeContainer();
|
||
|
|
|
||
|
|
for (int i = 0; i < craftingSystem.availableRecipes.Count; i++)
|
||
|
|
{
|
||
|
|
RecipeData recipe = craftingSystem.availableRecipes[i];
|
||
|
|
if (recipe == null)
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
GameObject buttonObject = Instantiate(recipeButtonPrefab, recipeContainer);
|
||
|
|
buttonObject.SetActive(true);
|
||
|
|
ConfigureRecipeButtonFrame(buttonObject, i);
|
||
|
|
recipeButtons.Add(buttonObject);
|
||
|
|
|
||
|
|
Button button = buttonObject.GetComponent<Button>();
|
||
|
|
if (button != null)
|
||
|
|
{
|
||
|
|
RecipeData capturedRecipe = recipe;
|
||
|
|
button.onClick.AddListener(() => OnCraftButtonClicked(capturedRecipe));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
RefreshRecipeButtons();
|
||
|
|
if (selectedRecipe == null && craftingSystem.availableRecipes.Count > 0)
|
||
|
|
{
|
||
|
|
SelectRecipe(craftingSystem.availableRecipes[0]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void RefreshRecipeButtons()
|
||
|
|
{
|
||
|
|
if (craftingSystem == null)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int i = 0; i < recipeButtons.Count; i++)
|
||
|
|
{
|
||
|
|
GameObject buttonObject = recipeButtons[i];
|
||
|
|
RecipeData recipe = i < craftingSystem.availableRecipes.Count ? craftingSystem.availableRecipes[i] : null;
|
||
|
|
if (buttonObject == null || recipe == null)
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool canCraft = craftingSystem.CanCraft(recipe);
|
||
|
|
Button button = buttonObject.GetComponent<Button>();
|
||
|
|
if (button != null)
|
||
|
|
{
|
||
|
|
button.interactable = canCraft;
|
||
|
|
}
|
||
|
|
|
||
|
|
Image background = buttonObject.GetComponent<Image>();
|
||
|
|
if (background != null)
|
||
|
|
{
|
||
|
|
background.color = canCraft
|
||
|
|
? new Color(0.12f, 0.24f, 0.18f, 0.98f)
|
||
|
|
: new Color(0.13f, 0.16f, 0.18f, 0.98f);
|
||
|
|
}
|
||
|
|
|
||
|
|
Image stateStripe = buttonObject.transform.Find("StateStripe")?.GetComponent<Image>();
|
||
|
|
if (stateStripe != null)
|
||
|
|
{
|
||
|
|
stateStripe.color = canCraft
|
||
|
|
? new Color(0.25f, 0.75f, 0.38f, 1f)
|
||
|
|
: new Color(0.44f, 0.48f, 0.52f, 1f);
|
||
|
|
}
|
||
|
|
|
||
|
|
Text title = buttonObject.transform.Find("Title")?.GetComponent<Text>();
|
||
|
|
if (title != null)
|
||
|
|
{
|
||
|
|
title.text = recipe.recipeName;
|
||
|
|
}
|
||
|
|
|
||
|
|
Text result = buttonObject.transform.Find("Result")?.GetComponent<Text>();
|
||
|
|
if (result != null)
|
||
|
|
{
|
||
|
|
result.text = recipe.GetResultText();
|
||
|
|
}
|
||
|
|
|
||
|
|
Text ingredients = buttonObject.transform.Find("Ingredients")?.GetComponent<Text>();
|
||
|
|
if (ingredients != null)
|
||
|
|
{
|
||
|
|
ingredients.text = recipe.GetIngredientsText();
|
||
|
|
}
|
||
|
|
|
||
|
|
Text status = buttonObject.transform.Find("Status")?.GetComponent<Text>();
|
||
|
|
if (status != null)
|
||
|
|
{
|
||
|
|
status.text = canCraft ? "ГОТОВО" : "НЕТ РЕС.";
|
||
|
|
status.color = canCraft
|
||
|
|
? new Color(0.76f, 0.96f, 0.72f)
|
||
|
|
: new Color(0.94f, 0.72f, 0.62f);
|
||
|
|
}
|
||
|
|
|
||
|
|
Text label = buttonObject.transform.Find("Label")?.GetComponent<Text>();
|
||
|
|
if (label != null)
|
||
|
|
{
|
||
|
|
label.gameObject.SetActive(false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (messageText != null)
|
||
|
|
{
|
||
|
|
messageText.text = craftingSystem.lastMessage;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (selectedRecipe != null)
|
||
|
|
{
|
||
|
|
SelectRecipe(selectedRecipe);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void SelectRecipe(RecipeData recipe)
|
||
|
|
{
|
||
|
|
selectedRecipe = recipe;
|
||
|
|
if (selectedRecipeText == null)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (recipe == null)
|
||
|
|
{
|
||
|
|
selectedRecipeText.text = "Рецепт не выбран";
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
string missing = craftingSystem != null && !craftingSystem.CanCraft(recipe)
|
||
|
|
? "\nНе хватает: " + craftingSystem.GetMissingIngredientsText(recipe)
|
||
|
|
: "\nМожно создать сейчас.";
|
||
|
|
|
||
|
|
selectedRecipeText.text =
|
||
|
|
recipe.recipeName + ": " + recipe.description + "\n" +
|
||
|
|
"Ингредиенты: " + recipe.GetIngredientsText() + "\n" +
|
||
|
|
"Результат: " + recipe.GetResultText() + missing;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void OnCraftButtonClicked(RecipeData recipe)
|
||
|
|
{
|
||
|
|
SelectRecipe(recipe);
|
||
|
|
if (craftingSystem != null)
|
||
|
|
{
|
||
|
|
craftingSystem.Craft(recipe);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void ClearRecipeButtons()
|
||
|
|
{
|
||
|
|
recipeButtons.Clear();
|
||
|
|
|
||
|
|
if (recipeContainer == null)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int i = recipeContainer.childCount - 1; i >= 0; i--)
|
||
|
|
{
|
||
|
|
Destroy(recipeContainer.GetChild(i).gameObject);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void ConfigureRecipeContainer()
|
||
|
|
{
|
||
|
|
RectTransform containerRect = recipeContainer as RectTransform;
|
||
|
|
if (containerRect == null)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
VerticalLayoutGroup layoutGroup = recipeContainer.GetComponent<VerticalLayoutGroup>();
|
||
|
|
if (layoutGroup != null)
|
||
|
|
{
|
||
|
|
layoutGroup.enabled = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
containerRect.anchorMin = new Vector2(0.5f, 0.5f);
|
||
|
|
containerRect.anchorMax = new Vector2(0.5f, 0.5f);
|
||
|
|
containerRect.pivot = new Vector2(0.5f, 0.5f);
|
||
|
|
containerRect.anchoredPosition = new Vector2(0f, -8f);
|
||
|
|
containerRect.sizeDelta = new Vector2(336f, 286f);
|
||
|
|
|
||
|
|
Image panelImage = GetComponent<Image>();
|
||
|
|
if (panelImage != null)
|
||
|
|
{
|
||
|
|
panelImage.color = new Color(0.055f, 0.070f, 0.085f, 0.97f);
|
||
|
|
}
|
||
|
|
|
||
|
|
Text title = transform.Find("Recipe Title")?.GetComponent<Text>();
|
||
|
|
if (title != null)
|
||
|
|
{
|
||
|
|
SetRect(title.rectTransform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 160f), new Vector2(336f, 30f), new Vector2(0.5f, 0.5f));
|
||
|
|
}
|
||
|
|
|
||
|
|
Text debug = transform.Find("Recipe Debug")?.GetComponent<Text>();
|
||
|
|
if (debug != null)
|
||
|
|
{
|
||
|
|
SetRect(debug.rectTransform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, -162f), new Vector2(336f, 24f), new Vector2(0.5f, 0.5f));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void ConfigureRecipeButtonFrame(GameObject buttonObject, int index)
|
||
|
|
{
|
||
|
|
RectTransform rect = buttonObject.GetComponent<RectTransform>();
|
||
|
|
if (rect != null)
|
||
|
|
{
|
||
|
|
rect.anchorMin = new Vector2(0f, 1f);
|
||
|
|
rect.anchorMax = new Vector2(0f, 1f);
|
||
|
|
rect.pivot = new Vector2(0f, 1f);
|
||
|
|
rect.anchoredPosition = new Vector2(0f, -index * 58f);
|
||
|
|
rect.sizeDelta = new Vector2(336f, 52f);
|
||
|
|
rect.localScale = Vector3.one;
|
||
|
|
}
|
||
|
|
|
||
|
|
Image background = buttonObject.GetComponent<Image>();
|
||
|
|
if (background != null)
|
||
|
|
{
|
||
|
|
background.color = new Color(0.13f, 0.16f, 0.18f, 0.98f);
|
||
|
|
}
|
||
|
|
|
||
|
|
Text oldLabel = buttonObject.transform.Find("Label")?.GetComponent<Text>();
|
||
|
|
Font font = ResolveUIFont(oldLabel);
|
||
|
|
if (oldLabel != null)
|
||
|
|
{
|
||
|
|
oldLabel.gameObject.SetActive(false);
|
||
|
|
}
|
||
|
|
|
||
|
|
Image stateStripe = EnsureImageChild(buttonObject.transform, "StateStripe", new Color(0.44f, 0.48f, 0.52f, 1f));
|
||
|
|
SetRect(stateStripe.rectTransform, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(3f, 0f), new Vector2(6f, 44f), new Vector2(0.5f, 0.5f));
|
||
|
|
|
||
|
|
Text title = EnsureTextChild(buttonObject.transform, "Title", font, 13, FontStyle.Bold, TextAnchor.UpperLeft, Color.white);
|
||
|
|
SetRect(title.rectTransform, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(110f, -10f), new Vector2(190f, 20f), new Vector2(0.5f, 0.5f));
|
||
|
|
|
||
|
|
Text result = EnsureTextChild(buttonObject.transform, "Result", font, 12, FontStyle.Bold, TextAnchor.UpperRight, new Color(0.78f, 0.92f, 1f));
|
||
|
|
SetRect(result.rectTransform, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-58f, -10f), new Vector2(100f, 20f), new Vector2(0.5f, 0.5f));
|
||
|
|
|
||
|
|
Text ingredients = EnsureTextChild(buttonObject.transform, "Ingredients", font, 9, FontStyle.Normal, TextAnchor.LowerLeft, new Color(0.82f, 0.86f, 0.88f));
|
||
|
|
ingredients.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||
|
|
ingredients.verticalOverflow = VerticalWrapMode.Truncate;
|
||
|
|
SetRect(ingredients.rectTransform, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(130f, 12f), new Vector2(230f, 20f), new Vector2(0.5f, 0.5f));
|
||
|
|
|
||
|
|
Text status = EnsureTextChild(buttonObject.transform, "Status", font, 10, FontStyle.Bold, TextAnchor.LowerRight, new Color(0.94f, 0.72f, 0.62f));
|
||
|
|
SetRect(status.rectTransform, new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(-46f, 12f), new Vector2(76f, 18f), new Vector2(0.5f, 0.5f));
|
||
|
|
}
|
||
|
|
|
||
|
|
private Text EnsureTextChild(Transform parent, string childName, Font font, int fontSize, FontStyle style, TextAnchor alignment, Color color)
|
||
|
|
{
|
||
|
|
Transform existing = parent.Find(childName);
|
||
|
|
GameObject child = existing != null ? existing.gameObject : new GameObject(childName, typeof(RectTransform), typeof(Text));
|
||
|
|
child.transform.SetParent(parent, false);
|
||
|
|
|
||
|
|
Text text = child.GetComponent<Text>();
|
||
|
|
text.font = font != null ? font : ResolveUIFont(null);
|
||
|
|
text.fontSize = fontSize;
|
||
|
|
text.fontStyle = style;
|
||
|
|
text.alignment = alignment;
|
||
|
|
text.color = color;
|
||
|
|
text.raycastTarget = false;
|
||
|
|
text.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||
|
|
text.verticalOverflow = VerticalWrapMode.Truncate;
|
||
|
|
child.SetActive(true);
|
||
|
|
return text;
|
||
|
|
}
|
||
|
|
|
||
|
|
private Font ResolveUIFont(Text preferredText)
|
||
|
|
{
|
||
|
|
if (uiFont != null)
|
||
|
|
{
|
||
|
|
return uiFont;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (preferredText != null && preferredText.font != null)
|
||
|
|
{
|
||
|
|
uiFont = preferredText.font;
|
||
|
|
return uiFont;
|
||
|
|
}
|
||
|
|
|
||
|
|
Canvas canvas = GetComponentInParent<Canvas>();
|
||
|
|
if (canvas != null)
|
||
|
|
{
|
||
|
|
Text[] texts = canvas.GetComponentsInChildren<Text>(true);
|
||
|
|
for (int i = 0; i < texts.Length; i++)
|
||
|
|
{
|
||
|
|
if (texts[i] != null && texts[i].font != null && texts[i].font.name.ToLowerInvariant().Contains("ubuntu"))
|
||
|
|
{
|
||
|
|
uiFont = texts[i].font;
|
||
|
|
return uiFont;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int i = 0; i < texts.Length; i++)
|
||
|
|
{
|
||
|
|
if (texts[i] != null && texts[i].font != null)
|
||
|
|
{
|
||
|
|
uiFont = texts[i].font;
|
||
|
|
return uiFont;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
uiFont = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
|
||
|
|
return uiFont;
|
||
|
|
}
|
||
|
|
|
||
|
|
private Image EnsureImageChild(Transform parent, string childName, Color color)
|
||
|
|
{
|
||
|
|
Transform existing = parent.Find(childName);
|
||
|
|
GameObject child = existing != null ? existing.gameObject : new GameObject(childName, typeof(RectTransform), typeof(Image));
|
||
|
|
child.transform.SetParent(parent, false);
|
||
|
|
|
||
|
|
Image image = child.GetComponent<Image>();
|
||
|
|
image.color = color;
|
||
|
|
image.raycastTarget = false;
|
||
|
|
child.SetActive(true);
|
||
|
|
return image;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void SetRect(RectTransform rect, Vector2 anchorMin, Vector2 anchorMax, Vector2 anchoredPosition, Vector2 sizeDelta, Vector2 pivot)
|
||
|
|
{
|
||
|
|
rect.anchorMin = anchorMin;
|
||
|
|
rect.anchorMax = anchorMax;
|
||
|
|
rect.pivot = pivot;
|
||
|
|
rect.anchoredPosition = anchoredPosition;
|
||
|
|
rect.sizeDelta = sizeDelta;
|
||
|
|
rect.localScale = Vector3.one;
|
||
|
|
}
|
||
|
|
}
|