ShoppingController.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. using Newtonsoft.Json;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using Unity.VisualScripting;
  6. using UnityEngine;
  7. using UnityEngine.SceneManagement;
  8. using UnityEngine.SocialPlatforms.Impl;
  9. using UnityEngine.UIElements;
  10. /* 这个controller 是用于控制 Shopping UI菜单的
  11. */
  12. public class ShoppingController : MonoBehaviour
  13. {
  14. // Start is called before the first frame update
  15. // 主页面元素
  16. private Button foodButton, toyButton, otherButton, backButton;
  17. private Label coinQty;
  18. private List<ItemInShop> shoppingItems = new();
  19. private VisualElement itemListView;
  20. //弹窗元素
  21. private Button yesButton, noButton;
  22. private Label msgBody;
  23. private VisualElement msgRoot, msgField;
  24. // 选中的产品
  25. private string selectedItemId, selectedItemDesc, selectedItemPrice;
  26. void OnEnable()
  27. {
  28. // 基层元素获取
  29. var root = GetComponent<UIDocument>().rootVisualElement;
  30. var mainManu = root.Q<VisualElement>("mainManu");
  31. itemListView = root.Q<VisualElement>("itemListView");
  32. foodButton = mainManu.Q<Button>("food");
  33. foodButton.clicked += () => TabSwitch(foodButton);
  34. toyButton = mainManu.Q<Button>("toy");
  35. toyButton.clicked += () => TabSwitch(toyButton);
  36. otherButton = mainManu.Q<Button>("other");
  37. otherButton.clicked += () => TabSwitch(otherButton);
  38. var coinArea = root.Q<VisualElement>("coinArea");
  39. coinQty = coinArea.Q<Label>("coinQty");
  40. backButton = root.Q<Button>("back");
  41. // 绑定事件
  42. backButton.clicked += BackBtnClick;
  43. // 弹窗元素获取
  44. msgRoot = root.Q<VisualElement>("msgRoot");
  45. msgField = msgRoot.Q<VisualElement>("msgField");
  46. msgBody = msgField.Q<Label>("msgBody");
  47. yesButton = msgField.Q<Button>("msgYes");
  48. noButton = msgField.Q<Button>("msgNo");
  49. noButton.clicked += MsgNoClick;
  50. yesButton.clicked += MsgYesClick;
  51. //初始化设定
  52. LanguageSetting();
  53. DataLoading();
  54. GetItemList("food");
  55. foodButton.transform.scale = new Vector3(1.2f, 1.2f);
  56. InstallItems("food");
  57. }
  58. private void OnDisable()
  59. {
  60. shoppingItems.Clear(); // 因为启动时候调用OnEable数据会被重复加载
  61. }
  62. // Update is called once per frame
  63. //void Update()
  64. //{
  65. //}
  66. //菜单语言设定
  67. void LanguageSetting()
  68. {
  69. // 设置 shopping UI界面里面label和按键的语言显示
  70. string textValue = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "shoppingUI", "button", "food", EnviromentSetting.languageCode });
  71. foodButton.text = textValue;
  72. textValue = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "shoppingUI", "button", "toy", EnviromentSetting.languageCode });
  73. toyButton.text = textValue;
  74. textValue = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "shoppingUI", "button", "other", EnviromentSetting.languageCode });
  75. otherButton.text = textValue;
  76. textValue = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "shoppingUI", "button", "back", EnviromentSetting.languageCode });
  77. backButton.text = textValue;
  78. textValue = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "shoppingUI", "button", "yes", EnviromentSetting.languageCode });
  79. yesButton.text = textValue;
  80. textValue = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "shoppingUI", "button", "no", EnviromentSetting.languageCode });
  81. noButton.text = textValue;
  82. }
  83. /*获取所有产品列表,切换商品分类之后,需要重新读取和加载
  84. */
  85. void GetItemList(string type)
  86. {
  87. // 按照类别获取shopping items
  88. shoppingItems.Clear();
  89. string itemRawData = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "item", type});
  90. Dictionary<string, object> itemDict = JsonConvert.DeserializeObject<Dictionary<string, object>>(itemRawData);
  91. foreach (string _item in itemDict.Keys)
  92. {
  93. var itemDetail = JsonConvert.DeserializeObject<Dictionary<string, object>>(itemDict[_item].ToString());
  94. string price = itemDetail["price"].ToString();
  95. string picture = itemDetail["picture"].ToString();
  96. var desc = JsonConvert.DeserializeObject<Dictionary<string, object>>(itemDetail["description"].ToString());
  97. string description = desc[EnviromentSetting.languageCode].ToString();
  98. // 检测toy是否达到最大可以拥有的数量,如果达到就不再添加
  99. if (type == "toy")
  100. {
  101. if(!UserProperty.toy.TryGetValue(_item, out int qty))
  102. {
  103. // 如果用户没有这个道具,就商品里面添加这个道具
  104. ItemInShop SearchedItem = new(_item, description, price, picture);
  105. shoppingItems.Add(SearchedItem);
  106. }
  107. else
  108. {
  109. // 如果用户有这个,并且拥有数量小于最大值,就商品里面添加这个道具
  110. if (qty < int.Parse(itemDetail["max qty"].ToString()))
  111. {
  112. ItemInShop SearchedItem = new(_item, description, price, picture);
  113. shoppingItems.Add(SearchedItem);
  114. }
  115. }
  116. }
  117. // 检测food是否达到最大可以拥有的数量,如果达到就不再添加
  118. if (type == "food")
  119. {
  120. if (!UserProperty.food.TryGetValue(_item, out int qty))
  121. {
  122. // 如果用户没有这个道具,就商品里面添加这个道具
  123. ItemInShop SearchedItem = new(_item, description, price, picture);
  124. shoppingItems.Add(SearchedItem);
  125. }
  126. else
  127. {
  128. // 如果用户有这个,并且拥有数量小于最大值,就商品里面添加这个道具
  129. if (qty < int.Parse(itemDetail["max qty"].ToString()))
  130. {
  131. ItemInShop SearchedItem = new(_item, description, price, picture);
  132. shoppingItems.Add(SearchedItem);
  133. }
  134. }
  135. }
  136. // 检测other是否达到最大可以拥有的数量,如果达到就不再添加
  137. if (type == "other")
  138. {
  139. if (!UserProperty.other.TryGetValue(_item, out int qty))
  140. {
  141. // 如果用户没有这个道具,就商品里面添加这个道具
  142. ItemInShop SearchedItem = new(_item, description, price, picture);
  143. shoppingItems.Add(SearchedItem);
  144. }
  145. else
  146. {
  147. // 如果用户有这个,并且拥有数量小于最大值,就商品里面添加这个道具
  148. if (qty < int.Parse(itemDetail["max qty"].ToString()))
  149. {
  150. ItemInShop SearchedItem = new(_item, description, price, picture);
  151. shoppingItems.Add(SearchedItem);
  152. }
  153. }
  154. }
  155. }
  156. }
  157. // 将items装载到菜单中,切换商品分类之后,需要重新读取和加载
  158. void InstallItems(string type)
  159. {
  160. var root = GetComponent<UIDocument>().rootVisualElement;
  161. itemListView.Clear();
  162. VisualTreeAsset itemResource = Resources.Load<VisualTreeAsset>("Shopping/Item");
  163. List<ItemInShop> items = new();
  164. foreach(var item in shoppingItems)
  165. {
  166. var itemFrame = new VisualElement();
  167. itemFrame = itemResource.CloneTree();
  168. var description = itemFrame.Q<Label>("description");
  169. description.text = item.description;
  170. var price = itemFrame.Q<Label>("price");
  171. price.text = "$ "+item.price;
  172. var texture = Resources.Load<Texture2D>(item.picture);
  173. var picture = itemFrame.Q<VisualElement>("picture");
  174. picture.style.backgroundImage = new StyleBackground(texture);
  175. itemFrame.RegisterCallback<ClickEvent>(e => ItemClick(e, item.id, item.description, item.price));
  176. itemListView.Add(itemFrame);
  177. }
  178. }
  179. // 点击商品后跳出确认窗口
  180. void ItemClick(ClickEvent clickEvent, string itemId, string description, string price)
  181. {
  182. selectedItemId = itemId;
  183. selectedItemDesc = description;
  184. selectedItemPrice = price;
  185. msgBody.text = description;
  186. msgRoot.visible = true;
  187. }
  188. // 数据读取
  189. void DataLoading()
  190. {
  191. // 游戏金币数量读取
  192. coinQty.text = UserProperty.coin.ToString();
  193. }
  194. void TabSwitch(Button btn)
  195. {
  196. itemListView.style.backgroundColor = btn.resolvedStyle.backgroundColor;
  197. foodButton.transform.scale = new Vector3(1f, 1f, 1);
  198. toyButton.transform.scale = new Vector3(1f, 1f, 1);
  199. otherButton.transform.scale = new Vector3(1f, 1f, 1);
  200. btn.transform.scale = new Vector3(1.2f, 1.2f, 1);
  201. itemListView.Clear();
  202. HomeSoundEffectController.Instance.PlaySoundEffect(0);
  203. // 这里btn.name必须和json里面商品类别完全匹配
  204. GetItemList(btn.name);
  205. InstallItems(btn.name);
  206. }
  207. // msg no button 点击
  208. void MsgNoClick()
  209. {
  210. msgRoot.visible = false;
  211. }
  212. // msg yes button 点击
  213. void MsgYesClick()
  214. {
  215. Debug.Log("msg yes clicked");
  216. msgRoot.visible = false;
  217. // 检测用户金币是否足够
  218. if (UserProperty.coin > int.Parse(selectedItemPrice))
  219. {
  220. PurchaseItemRequest(selectedItemId);
  221. }
  222. else
  223. {
  224. string msg = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "shoppingUI", "message", "not_enough_coin", EnviromentSetting.languageCode });
  225. MessageBoxController.ShowMessage(msg);
  226. }
  227. }
  228. void BackBtnClick()
  229. {
  230. HomeSoundEffectController.Instance.PlaySoundEffect(2);
  231. var uiPlaceholder = GameObject.Find("UI Placeholder");
  232. if (uiPlaceholder != null)
  233. {
  234. var shoppingUI = uiPlaceholder.transform.Find("ShoppingUI").gameObject;
  235. var vamUI = uiPlaceholder.transform.Find("VoiceAndMenu").gameObject;
  236. shoppingUI.SetActive(false);
  237. vamUI.SetActive(true);
  238. }
  239. }
  240. // 购物request
  241. void PurchaseItemRequest(string itemId)
  242. {
  243. Debug.Log("Purchase item request");
  244. string url = "/api/item/puchase/";
  245. WWWForm form = new();
  246. form.AddField("user_id", UserProperty.userId);
  247. form.AddField("item_id", itemId);
  248. form.AddField("qty", 1);
  249. StartCoroutine(WebController.PostRequest(url, form, callback: PurchaseItemCallback));
  250. }
  251. void PurchaseItemCallback(string json)
  252. {
  253. var data = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
  254. if (data != null && data["status"].ToString() == "success")
  255. {
  256. HomeSoundEffectController.Instance.PlaySoundEffect(3);
  257. // 重新写入用户数据
  258. string userInfo = data["user_info"].ToString();
  259. UserProperty.FreshUserInfo(userInfo);
  260. // TODO 然后重新写入道具数据
  261. UserProperty.food.Clear();
  262. UserProperty.toy.Clear();
  263. UserProperty.other.Clear();
  264. // 弹出窗户提示购买成功
  265. string msg = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "shoppingUI", "message", "purchase_success", EnviromentSetting.languageCode });
  266. msg = msg.Replace("<<item_name>>", selectedItemDesc);
  267. MessageBoxController.ShowMessage(msg);
  268. }
  269. else
  270. {
  271. Debug.Log(data["message"]);
  272. }
  273. }
  274. }
  275. public class ItemInShop
  276. {
  277. public string id;
  278. public string description;
  279. public string picture;
  280. public string price;
  281. public ItemInShop(string id, string desc, string price, string picture) {
  282. this.id = id;
  283. this.description = desc;
  284. this.price = price;
  285. this.picture = picture;
  286. }
  287. }