Initial commit: Unity WordConnect project
This commit is contained in:
118
Assets/WordConnectGameToolkit/Scripts/GUI/AnimateTransform.cs
Normal file
118
Assets/WordConnectGameToolkit/Scripts/GUI/AnimateTransform.cs
Normal file
@ -0,0 +1,118 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI
|
||||
{
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
public class AnimateTransform : MonoBehaviour
|
||||
{
|
||||
public Move position;
|
||||
public Rotate rotation;
|
||||
public Scale scale;
|
||||
public Size sizeDelta;
|
||||
|
||||
private RectTransform rectTransform;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
rectTransform = GetComponent<RectTransform>();
|
||||
|
||||
if (position.targetValue != Vector3.zero)
|
||||
{
|
||||
rectTransform.anchoredPosition = position.startValue;
|
||||
position.Animate(rectTransform);
|
||||
}
|
||||
|
||||
if (rotation.targetValue != Vector3.zero)
|
||||
{
|
||||
rectTransform.eulerAngles = rotation.startValue;
|
||||
rotation.Animate(rectTransform);
|
||||
}
|
||||
|
||||
if (scale.targetValue != Vector3.zero)
|
||||
{
|
||||
rectTransform.localScale = scale.startValue;
|
||||
scale.Animate(rectTransform);
|
||||
}
|
||||
|
||||
if (sizeDelta.targetValue != Vector3.zero)
|
||||
{
|
||||
rectTransform.sizeDelta = sizeDelta.startValue;
|
||||
sizeDelta.Animate(rectTransform);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
rectTransform.DOKill();
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public abstract class TweenAnimationParameters
|
||||
{
|
||||
public Vector3 startValue;
|
||||
public Vector3 targetValue;
|
||||
public float duration = 1f;
|
||||
public float delay;
|
||||
public Ease easeType = Ease.Linear;
|
||||
public bool loop;
|
||||
public LoopType loopType;
|
||||
|
||||
public void Animate(RectTransform rectTransform)
|
||||
{
|
||||
GetTween(rectTransform).SetEase(easeType).SetDelay(delay).SetLoops(loop ? -1 : 1, loopType);
|
||||
}
|
||||
|
||||
protected abstract Tweener GetTween(RectTransform rectTransform);
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class Move : TweenAnimationParameters
|
||||
{
|
||||
protected override Tweener GetTween(RectTransform rectTransform)
|
||||
{
|
||||
return rectTransform.DOLocalMove(targetValue, duration);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class Rotate : TweenAnimationParameters
|
||||
{
|
||||
protected override Tweener GetTween(RectTransform rectTransform)
|
||||
{
|
||||
return rectTransform.DOLocalRotate(targetValue, duration);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class Scale : TweenAnimationParameters
|
||||
{
|
||||
protected override Tweener GetTween(RectTransform rectTransform)
|
||||
{
|
||||
return rectTransform.DOScale(targetValue, duration);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class Size : TweenAnimationParameters
|
||||
{
|
||||
protected override Tweener GetTween(RectTransform rectTransform)
|
||||
{
|
||||
return rectTransform.DOSizeDelta(targetValue, duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cadee4a7f70a470daf9c57afd1455652
|
||||
timeCreated: 1692895718
|
||||
@ -0,0 +1,84 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using VContainer;
|
||||
using WordsToolkit.Scripts.Gameplay.Managers;
|
||||
using WordsToolkit.Scripts.Infrastructure.Service;
|
||||
using WordsToolkit.Scripts.Levels;
|
||||
using WordsToolkit.Scripts.Popups;
|
||||
using WordsToolkit.Scripts.System;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI
|
||||
{
|
||||
public class BackgroundChanger : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private Image image;
|
||||
|
||||
private ILevelLoaderService levelLoaderService;
|
||||
private StateManager stateManager;
|
||||
[SerializeField]
|
||||
private Sprite mainBackground;
|
||||
|
||||
[Inject]
|
||||
public void Construct(ILevelLoaderService levelLoaderService, StateManager stateManager)
|
||||
{
|
||||
this.levelLoaderService = levelLoaderService;
|
||||
this.levelLoaderService.OnLevelLoaded += OnLevelLoaded;
|
||||
SceneLoader.OnGameStart += SetBack;
|
||||
this.stateManager = stateManager;
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
stateManager.OnStateChanged.AddListener(OnStateChanged);
|
||||
}
|
||||
|
||||
private void OnStateChanged(EScreenStates arg0)
|
||||
{
|
||||
if (arg0 == EScreenStates.Game)
|
||||
{
|
||||
SetBack();
|
||||
}else if (arg0 == EScreenStates.MainMenu)
|
||||
{
|
||||
image.sprite = mainBackground;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetBack()
|
||||
{
|
||||
image.sprite = GameDataManager.GetLevel().background;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (levelLoaderService != null)
|
||||
{
|
||||
levelLoaderService.OnLevelLoaded -= OnLevelLoaded;
|
||||
SceneLoader.OnGameStart -= SetBack;
|
||||
stateManager.OnStateChanged.RemoveListener(OnStateChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLevelLoaded(Level level)
|
||||
{
|
||||
image.sprite = level.background;
|
||||
}
|
||||
|
||||
public void SetBackground(Sprite bg)
|
||||
{
|
||||
image.sprite = bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 59912d2c0926422a8517e192d9ecc7f6
|
||||
timeCreated: 1730130790
|
||||
3
Assets/WordConnectGameToolkit/Scripts/GUI/Buttons.meta
Normal file
3
Assets/WordConnectGameToolkit/Scripts/GUI/Buttons.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 716a5963d39e49cfad01e43eff89511f
|
||||
timeCreated: 1748674096
|
||||
@ -0,0 +1,69 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
using VContainer;
|
||||
using WordsToolkit.Scripts.Data;
|
||||
using WordsToolkit.Scripts.Gameplay.Managers;
|
||||
using WordsToolkit.Scripts.Settings;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Buttons
|
||||
{
|
||||
public class BaseGUIButton : CustomButton, IFadeable
|
||||
{
|
||||
protected LevelManager levelManager;
|
||||
protected GameSettings gameSettings;
|
||||
protected ResourceManager resourceManager;
|
||||
protected ButtonViewController buttonViewController;
|
||||
public RectTransform rectTransform;
|
||||
public Vector2 savePosition;
|
||||
public Vector2 targetPosition;
|
||||
|
||||
[Inject]
|
||||
public void Construct(LevelManager levelManager, GameSettings gameSettings, ResourceManager resourceManager, ButtonViewController buttonViewController)
|
||||
{
|
||||
this.gameSettings = gameSettings;
|
||||
this.levelManager = levelManager;
|
||||
this.resourceManager = resourceManager;
|
||||
this.buttonViewController = buttonViewController;
|
||||
this.buttonViewController.RegisterButton(this);
|
||||
}
|
||||
|
||||
public void Hide()
|
||||
{
|
||||
animator.enabled = false;
|
||||
rectTransform.DOAnchorPos( targetPosition, 0.5f);
|
||||
}
|
||||
|
||||
public void InstantHide()
|
||||
{
|
||||
rectTransform.anchoredPosition = targetPosition;
|
||||
}
|
||||
|
||||
public void HideForWin()
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
|
||||
public void Show()
|
||||
{
|
||||
animator.enabled = true;
|
||||
rectTransform.DOAnchorPos(savePosition, 0.5f).OnComplete(ShowCallback);
|
||||
}
|
||||
|
||||
protected virtual void ShowCallback()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eae64b3976cb4849bb325653a674bfd0
|
||||
timeCreated: 1748758607
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b4baa2b47c0445f7837eea134618de67
|
||||
timeCreated: 1748527950
|
||||
@ -0,0 +1,139 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System.Linq;
|
||||
using DG.Tweening;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using WordsToolkit.Scripts.Data;
|
||||
using WordsToolkit.Scripts.System;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Buttons.Boosts
|
||||
{
|
||||
public abstract class BaseBoostButton : BaseGUIButton
|
||||
{
|
||||
public ResourceObject resourceToPay;
|
||||
public ResourceObject resourseToHoldBoost;
|
||||
public TextMeshProUGUI price;
|
||||
public TextMeshProUGUI countText;
|
||||
public GameObject priceObject;
|
||||
public GameObject countTextObject;
|
||||
protected int count;
|
||||
|
||||
[SerializeField]
|
||||
private ParticleSystem waves;
|
||||
|
||||
private CanvasGroup canvasGroup;
|
||||
private bool isActive;
|
||||
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
return;
|
||||
}
|
||||
InitializePrice();
|
||||
UpdatePriceDisplay();
|
||||
onClick.AddListener(OnClick);
|
||||
var main = waves.main;
|
||||
main.prewarm = true; // Start particles in grown state
|
||||
main.loop = true;
|
||||
waves.Stop(); // Ensure it's not auto-playing
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
onClick.RemoveListener(OnClick);
|
||||
}
|
||||
|
||||
protected abstract void InitializePrice();
|
||||
|
||||
public virtual void UpdatePriceDisplay()
|
||||
{
|
||||
// If we have resources in the hold boost, show that count
|
||||
if (resourseToHoldBoost != null && resourseToHoldBoost.GetValue() > 0)
|
||||
{
|
||||
countTextObject.gameObject.SetActive(true);
|
||||
priceObject.gameObject.SetActive(false);
|
||||
countText.text = resourseToHoldBoost.GetValue().ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
countTextObject.gameObject.SetActive(false);
|
||||
priceObject.gameObject.SetActive(true);
|
||||
price.text = count.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnClick()
|
||||
{
|
||||
if (isActive)
|
||||
{
|
||||
Refund();
|
||||
DeactivateBoost();
|
||||
return;
|
||||
}
|
||||
if (resourceManager.Consume(resourseToHoldBoost, 1))
|
||||
{
|
||||
ActivateBoost();
|
||||
}
|
||||
// If not, consume from the regular resource
|
||||
else if (resourceManager.ConsumeWithEffects(resourceToPay, count))
|
||||
{
|
||||
resourseToHoldBoost.Add(gameSettings.countOfBoostsToBuy);
|
||||
UpdatePriceDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
private void Refund()
|
||||
{
|
||||
resourseToHoldBoost.Add(1);
|
||||
UpdatePriceDisplay();
|
||||
}
|
||||
|
||||
protected virtual void ActivateBoost(bool hideButtons = true)
|
||||
{
|
||||
UpdatePriceDisplay();
|
||||
if(hideButtons)
|
||||
buttonViewController.HideOtherButtons(this);
|
||||
PulseAnimation();
|
||||
waves.Play();
|
||||
isActive = true;
|
||||
priceObject.SetActive(false);
|
||||
countTextObject.SetActive(false);
|
||||
}
|
||||
protected virtual void DeactivateBoost()
|
||||
{
|
||||
isActive = false;
|
||||
buttonViewController.ShowButtons();
|
||||
waves.Clear();
|
||||
waves.Stop();
|
||||
DOTween.Complete(transform);
|
||||
DOTween.Kill(transform);
|
||||
transform.localScale = Vector3.one;
|
||||
UpdatePriceDisplay();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void PulseAnimation()
|
||||
{
|
||||
animator.enabled = false;
|
||||
transform.DOScale(Vector3.one * 0.9f, 0.5f)
|
||||
.SetLoops(-1, LoopType.Yoyo)
|
||||
.SetEase(Ease.InOutSine);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 48df3644dc80e4cb9bcf75be337f8fc4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,49 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using WordsToolkit.Scripts.Enums;
|
||||
using WordsToolkit.Scripts.Gameplay;
|
||||
using WordsToolkit.Scripts.System;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Buttons.Boosts
|
||||
{
|
||||
public class HammerBoostButton : BaseBoostButton
|
||||
{
|
||||
protected override void InitializePrice()
|
||||
{
|
||||
count = gameSettings.hammerBoostPrice;
|
||||
UpdatePriceDisplay();
|
||||
}
|
||||
|
||||
protected override void ActivateBoost(bool hideButtons = true)
|
||||
{
|
||||
base.ActivateBoost(hideButtons);
|
||||
if (levelManager != null && !levelManager.hammerMode)
|
||||
{
|
||||
levelManager.hammerMode = true;
|
||||
EventManager.GetEvent<Tile>(EGameEvent.TileSelected).Subscribe(OnTileSelected);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTileSelected(Tile obj)
|
||||
{
|
||||
DeactivateBoost();
|
||||
}
|
||||
|
||||
protected override void DeactivateBoost()
|
||||
{
|
||||
levelManager.hammerMode = false;
|
||||
EventManager.GetEvent<Tile>(EGameEvent.TileSelected).Unsubscribe(OnTileSelected);
|
||||
base.DeactivateBoost();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cafdd253e27364743a17c8c205d36c4a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,37 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using WordsToolkit.Scripts.Gameplay.Managers;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Buttons.Boosts
|
||||
{
|
||||
public class TipBoostButton : BaseBoostButton
|
||||
{
|
||||
protected override void InitializePrice()
|
||||
{
|
||||
count = gameSettings.hintBoostPrice;
|
||||
UpdatePriceDisplay();
|
||||
}
|
||||
|
||||
protected override void ActivateBoost(bool hideButtons = true)
|
||||
{
|
||||
base.ActivateBoost(false);
|
||||
FindObjectOfType<FieldManager>().OpenRandomTile();
|
||||
DeactivateBoost();
|
||||
}
|
||||
|
||||
protected override void DeactivateBoost()
|
||||
{
|
||||
base.DeactivateBoost();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c9628c9e141543b6a064c5d3cb68180
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,88 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Buttons
|
||||
{
|
||||
public interface IShowable
|
||||
{
|
||||
void Show();
|
||||
}
|
||||
|
||||
public interface IHideable
|
||||
{
|
||||
void Hide();
|
||||
void InstantHide();
|
||||
}
|
||||
|
||||
public interface IHideableForWin
|
||||
{
|
||||
void HideForWin();
|
||||
}
|
||||
|
||||
public interface IFadeable : IShowable, IHideable{}
|
||||
|
||||
public class ButtonViewController
|
||||
{
|
||||
private HashSet<IShowable> buttons;
|
||||
|
||||
public void RegisterButton(IShowable button)
|
||||
{
|
||||
if (buttons == null)
|
||||
{
|
||||
buttons = new HashSet<IShowable>();
|
||||
}
|
||||
buttons.Add(button);
|
||||
if (button is IHideable hideable)
|
||||
{
|
||||
hideable.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
public void HideOtherButtons(IShowable except)
|
||||
{
|
||||
foreach (var button in buttons)
|
||||
{
|
||||
if (!ReferenceEquals(button, except) && button is IHideable hideable)
|
||||
{
|
||||
hideable.Hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowButtons()
|
||||
{
|
||||
foreach (var button in buttons)
|
||||
{
|
||||
button.Show();
|
||||
}
|
||||
}
|
||||
|
||||
public void HideAllForWin()
|
||||
{
|
||||
if (buttons == null) return;
|
||||
|
||||
foreach (var button in buttons)
|
||||
{
|
||||
if (button is IHideableForWin buttonForWin)
|
||||
{
|
||||
buttonForWin.HideForWin();
|
||||
}
|
||||
else if(button is IHideable hideable)
|
||||
{
|
||||
hideable.Hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 717db02c9e994b8ea966b55ece00dc54
|
||||
timeCreated: 1748601128
|
||||
@ -0,0 +1,116 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using VContainer;
|
||||
using WordsToolkit.Scripts.Audio;
|
||||
using WordsToolkit.Scripts.Enums;
|
||||
using WordsToolkit.Scripts.System;
|
||||
using WordsToolkit.Scripts.System.Haptic;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Buttons
|
||||
{
|
||||
[RequireComponent(typeof(Animator))]
|
||||
public class CustomButton : Button
|
||||
{
|
||||
public AudioClip overrideClickSound;
|
||||
public RuntimeAnimatorController overrideAnimatorController;
|
||||
private bool isClicked;
|
||||
private readonly float cooldownTime = .5f; // Cooldown time in seconds
|
||||
public new ButtonClickedEvent onClick;
|
||||
private new Animator animator;
|
||||
public bool noSound;
|
||||
|
||||
private static bool blockInput;
|
||||
|
||||
public static CustomButton latestClickedButton;
|
||||
private IAudioService audioService;
|
||||
[Inject]
|
||||
public void Construct(IAudioService audioService)
|
||||
{
|
||||
this.audioService = audioService;
|
||||
}
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
isClicked = false;
|
||||
// run only in runtime
|
||||
if (Application.isEditor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
base.OnEnable();
|
||||
animator = GetComponent<Animator>();
|
||||
if (overrideAnimatorController != null)
|
||||
{
|
||||
animator.runtimeAnimatorController = overrideAnimatorController;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
if (blockInput || isClicked || !interactable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (transition != Transition.Animation)
|
||||
{
|
||||
Pressed();
|
||||
}
|
||||
|
||||
isClicked = true;
|
||||
if(!noSound)
|
||||
audioService.PlayClick(overrideClickSound);
|
||||
HapticFeedback.TriggerHapticFeedback(HapticFeedback.HapticForce.Light);
|
||||
// Start cooldown
|
||||
if (gameObject.activeInHierarchy)
|
||||
{
|
||||
StartCoroutine(Cooldown());
|
||||
}
|
||||
|
||||
base.OnPointerClick(eventData);
|
||||
}
|
||||
|
||||
public void Pressed()
|
||||
{
|
||||
if (blockInput || !interactable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
latestClickedButton = this;
|
||||
onClick?.Invoke();
|
||||
EventManager.GetEvent<CustomButton>(EGameEvent.ButtonClicked).Invoke(this);
|
||||
}
|
||||
|
||||
private IEnumerator Cooldown()
|
||||
{
|
||||
yield return new WaitForSeconds(cooldownTime);
|
||||
isClicked = false;
|
||||
}
|
||||
|
||||
|
||||
private bool IsAnimationPlaying()
|
||||
{
|
||||
var stateInfo = animator.GetCurrentAnimatorStateInfo(0);
|
||||
return stateInfo.loop || stateInfo.normalizedTime < 1;
|
||||
}
|
||||
|
||||
public static void BlockInput(bool block)
|
||||
{
|
||||
blockInput = block;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9659348afa04bc6bb30eb6900f94b65
|
||||
timeCreated: 1725694504
|
||||
@ -0,0 +1,47 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Buttons
|
||||
{
|
||||
public class ExtraWordsButton : BaseGUIButton
|
||||
{
|
||||
private Coroutine occasionalPulseCoroutine;
|
||||
private bool pulseEnabled;
|
||||
private bool animated;
|
||||
|
||||
public void PulseAnimation(bool b)
|
||||
{
|
||||
pulseEnabled = b;
|
||||
if (b)
|
||||
{
|
||||
animator.Play($"PulseLoop");
|
||||
}
|
||||
else
|
||||
{
|
||||
animator.SetTrigger($"Pulse");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void ShowCallback()
|
||||
{
|
||||
base.ShowCallback();
|
||||
if (pulseEnabled)
|
||||
{
|
||||
PulseAnimation(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c3f8f7c7b8644ec9c726828e284a7dd
|
||||
timeCreated: 1748687127
|
||||
208
Assets/WordConnectGameToolkit/Scripts/GUI/Buttons/GiftButton.cs
Normal file
208
Assets/WordConnectGameToolkit/Scripts/GUI/Buttons/GiftButton.cs
Normal file
@ -0,0 +1,208 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using DG.Tweening;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using VContainer;
|
||||
using WordsToolkit.Scripts.Data;
|
||||
using WordsToolkit.Scripts.Enums;
|
||||
using WordsToolkit.Scripts.Popups;
|
||||
using WordsToolkit.Scripts.Settings;
|
||||
using WordsToolkit.Scripts.System;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Buttons
|
||||
{
|
||||
public class GiftButton : BaseGUIButton
|
||||
{
|
||||
private const string SAVE_KEY = "GiftButton_CollectedItems";
|
||||
|
||||
[Header("Counter Settings")]
|
||||
[SerializeField] private TextMeshProUGUI counterText;
|
||||
[SerializeField] private GameObject counterContainer;
|
||||
[SerializeField] private int collectedItems = 0;
|
||||
|
||||
[Header("Visual Feedback")]
|
||||
[SerializeField] private float pulseScale = 1.2f;
|
||||
[SerializeField] private float pulseDuration = 0.3f;
|
||||
|
||||
[Header("Resources")]
|
||||
[SerializeField] private ResourceObject resource;
|
||||
[Tooltip("Optional override for gems awarded per gift (if not set, uses value from GameSettings)")]
|
||||
[SerializeField] private int gemsPerGift = 0;
|
||||
[SerializeField] private TextMeshProUGUI gemsValueText;
|
||||
[SerializeField] private GameObject gemsLabelObject;
|
||||
|
||||
[Header("Visual Appearance")]
|
||||
[SerializeField] private Image mainBoxSprite;
|
||||
[SerializeField] private Sprite lightModeSprite;
|
||||
[SerializeField] private Sprite darkModeSprite;
|
||||
|
||||
[Inject]
|
||||
private MenuManager menuManager;
|
||||
|
||||
[SerializeField]
|
||||
private Popup giftPopup;
|
||||
|
||||
[Inject]
|
||||
private GameManager gameManager;
|
||||
|
||||
|
||||
|
||||
private bool isActive;
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
EventManager.GetEvent(EGameEvent.SpecialItemCollected).Subscribe(OnSpecialItemCollected);
|
||||
onClick.AddListener(ConsumeResource);
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
EventManager.GetEvent(EGameEvent.SpecialItemCollected).Unsubscribe(OnSpecialItemCollected);
|
||||
onClick.RemoveListener(ConsumeResource);
|
||||
}
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
if(!Application.isPlaying)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Load saved collected items
|
||||
collectedItems = PlayerPrefs.GetInt(SAVE_KEY, 0);
|
||||
|
||||
UpdateCounterDisplay();
|
||||
UpdateGemsValueDisplay();
|
||||
UpdateState();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the displayed gems value
|
||||
/// </summary>
|
||||
private void UpdateGemsValueDisplay()
|
||||
{
|
||||
if (gemsValueText != null)
|
||||
{
|
||||
int gemsAmount = gemsPerGift > 0 ?
|
||||
gemsPerGift :
|
||||
gameSettings.gemsForGift;
|
||||
|
||||
gemsValueText.text = gemsAmount.ToString();
|
||||
}
|
||||
|
||||
// Update visibility of gems label
|
||||
if (gemsLabelObject != null)
|
||||
{
|
||||
gemsLabelObject.SetActive(collectedItems > 0);
|
||||
}
|
||||
else if (gemsValueText != null)
|
||||
{
|
||||
// If no specific label object is assigned, control the text object directly
|
||||
gemsValueText.gameObject.SetActive(collectedItems > 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the visual state of the button based on collection status
|
||||
/// </summary>
|
||||
private void UpdateState()
|
||||
{
|
||||
isActive = collectedItems > 0;
|
||||
interactable = isActive;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increments the counter when a special item is collected
|
||||
/// </summary>
|
||||
public void CollectItem()
|
||||
{
|
||||
collectedItems++;
|
||||
// Save the updated count
|
||||
PlayerPrefs.SetInt(SAVE_KEY, collectedItems);
|
||||
PlayerPrefs.Save();
|
||||
|
||||
UpdateCounterDisplay();
|
||||
UpdateGemsValueDisplay();
|
||||
UpdateState();
|
||||
PlayCollectionFeedback();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the counter UI text
|
||||
/// </summary>
|
||||
private void UpdateCounterDisplay()
|
||||
{
|
||||
if (counterText != null)
|
||||
{
|
||||
counterText.text = collectedItems.ToString();
|
||||
}
|
||||
|
||||
// Show counter only if we've collected items
|
||||
if (counterContainer != null)
|
||||
{
|
||||
counterContainer.SetActive(collectedItems > 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void ConsumeResource()
|
||||
{
|
||||
// Get the gems amount from GameSettings or use the override if set
|
||||
int gemsAmount = gemsPerGift > 0 ?
|
||||
gemsPerGift :
|
||||
gameSettings.gemsForGift;
|
||||
|
||||
// Attempt to consume the resource and add gems
|
||||
if (resource != null && resourceManager.ConsumeWithEffects(resource,gemsAmount))
|
||||
{
|
||||
// Decrease the counter
|
||||
collectedItems--;
|
||||
// Save the updated count
|
||||
PlayerPrefs.SetInt(SAVE_KEY, collectedItems);
|
||||
PlayerPrefs.Save();
|
||||
|
||||
// Update the display
|
||||
UpdateCounterDisplay();
|
||||
UpdateGemsValueDisplay();
|
||||
UpdateState();
|
||||
|
||||
menuManager.ShowPopup(giftPopup);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Play visual feedback when item is collected
|
||||
/// </summary>
|
||||
private void PlayCollectionFeedback()
|
||||
{
|
||||
// Simple pulse animation
|
||||
mainBoxSprite.transform.DOScale(pulseScale, pulseDuration / 2)
|
||||
.SetEase(Ease.OutQuad)
|
||||
.OnComplete(() => {
|
||||
mainBoxSprite.transform.DOScale(1f, pulseDuration / 2).SetEase(Ease.InQuad);
|
||||
});
|
||||
}
|
||||
|
||||
// Event handler for when a special item is collected
|
||||
private void OnSpecialItemCollected()
|
||||
{
|
||||
CollectItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d3677e4b5b644088ad9a552da7f8f1b
|
||||
timeCreated: 1742478154
|
||||
24
Assets/WordConnectGameToolkit/Scripts/GUI/EffectDestroyer.cs
Normal file
24
Assets/WordConnectGameToolkit/Scripts/GUI/EffectDestroyer.cs
Normal file
@ -0,0 +1,24 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI
|
||||
{
|
||||
public class EffectDestroyer : MonoBehaviour
|
||||
{
|
||||
public void DestroyEffect()
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d70fddf960a6480eaa44d7e72f094f6a
|
||||
timeCreated: 1742997767
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 17f6ba929b9641c6800767ce10891c98
|
||||
timeCreated: 1742321438
|
||||
@ -0,0 +1,172 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using WordsToolkit.Scripts.Enums;
|
||||
using WordsToolkit.Scripts.Gameplay.Managers;
|
||||
using WordsToolkit.Scripts.Levels;
|
||||
using WordsToolkit.Scripts.System;
|
||||
using WordsToolkit.Scripts.Settings;
|
||||
using VContainer;
|
||||
using WordsToolkit.Scripts.NLP;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.ExtraWordBar
|
||||
{
|
||||
// Abstract base class for progress bars
|
||||
public abstract class BaseExtraWordsProgressBar : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Optional text display for progress")]
|
||||
public TextMeshProUGUI progressText;
|
||||
|
||||
[Tooltip("Format string for progress text. Use {0} for current, {1} for target")]
|
||||
public string textFormat = "{0}/{1}";
|
||||
|
||||
// Singleton instance for easy access from other scripts
|
||||
public static BaseExtraWordsProgressBar Instance { get; private set; }
|
||||
|
||||
// Protected field for max value that can be set by derived classes
|
||||
protected float maxValue = 1f;
|
||||
private LevelManager levelManager;
|
||||
private GameManager gameManager;
|
||||
private GameSettings gameSettings;
|
||||
private ICustomWordRepository wordRepository;
|
||||
|
||||
[Inject]
|
||||
public void Construct(LevelManager levelManager, GameManager gameManager, GameSettings gameSettings, ICustomWordRepository wordRepository)
|
||||
{
|
||||
this.levelManager = levelManager;
|
||||
this.gameManager = gameManager;
|
||||
this.gameSettings = gameSettings;
|
||||
this.wordRepository = wordRepository;
|
||||
}
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
UpdateMaxValueFromLevel();
|
||||
}
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
|
||||
EventManager.GetEvent<Level>(EGameEvent.LevelLoaded).Subscribe(OnLevelLoaded);
|
||||
// Make sure to update max value when enabled
|
||||
UpdateMaxValueFromLevel();
|
||||
UpdateProgressBar();
|
||||
}
|
||||
|
||||
private void OnExtraWordClaimed()
|
||||
{
|
||||
UpdateProgressBar();
|
||||
}
|
||||
|
||||
private void OnLevelLoaded(Level level)
|
||||
{
|
||||
EventManager.GetEvent<string>(EGameEvent.ExtraWordFound).Subscribe(OnExtraWordFound);
|
||||
EventManager.GetEvent(EGameEvent.ExtraWordClaimed).Subscribe(OnExtraWordClaimed);
|
||||
}
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
EventManager.GetEvent<string>(EGameEvent.ExtraWordFound).Unsubscribe(OnExtraWordFound);
|
||||
EventManager.GetEvent(EGameEvent.ExtraWordClaimed).Unsubscribe(OnExtraWordClaimed);
|
||||
EventManager.GetEvent<Level>(EGameEvent.LevelLoaded).Unsubscribe(OnLevelLoaded);
|
||||
}
|
||||
|
||||
protected virtual void OnExtraWordFound(string word)
|
||||
{
|
||||
// Update the progress bar when a new extra word is found
|
||||
UpdateProgressBar();
|
||||
}
|
||||
|
||||
public virtual void UpdateProgressBar()
|
||||
{
|
||||
if (levelManager == null)
|
||||
return;
|
||||
|
||||
// Get the current counts
|
||||
int targetExtraWords = GetTargetExtraWordsCount();
|
||||
int currentExtraWords = GetCurrentExtraWordsCount();
|
||||
|
||||
var currentValue = Mathf.Min(targetExtraWords, PlayerPrefs.GetInt("ExtraWordsCollected"));
|
||||
// Calculate the normalized progress value (0-1)
|
||||
float normalizedProgress = CalculateProgress(currentValue, targetExtraWords);
|
||||
// Update the specific UI component (each implementation can scale as needed)
|
||||
UpdateProgressDisplay(normalizedProgress);
|
||||
|
||||
// Update the text if available
|
||||
UpdateTextDisplay(currentValue, targetExtraWords);
|
||||
}
|
||||
|
||||
// Abstract method that must be implemented by derived classes
|
||||
protected abstract void UpdateProgressDisplay(float progress);
|
||||
|
||||
// New method to update max value from level data
|
||||
protected virtual void UpdateMaxValueFromLevel()
|
||||
{
|
||||
int targetExtraWords = GetTargetExtraWordsCount();
|
||||
SetMaxValue(targetExtraWords);
|
||||
}
|
||||
|
||||
// Method to set the max value for this progress bar
|
||||
public virtual void SetMaxValue(float value)
|
||||
{
|
||||
if (value <= 0)
|
||||
value = 1f; // Ensure we don't have invalid values
|
||||
|
||||
maxValue = value;
|
||||
|
||||
// Call implementation-specific method to apply the new max value
|
||||
ApplyMaxValue();
|
||||
}
|
||||
|
||||
// Virtual method that derived classes will override to apply max value to their specific component
|
||||
protected virtual void ApplyMaxValue()
|
||||
{
|
||||
// Base implementation does nothing
|
||||
}
|
||||
|
||||
// Gets the target extra words count from the current level's group or fallback to game settings
|
||||
protected int GetTargetExtraWordsCount()
|
||||
{
|
||||
var currentLevelGroup = GameDataManager.GetLevel().GetGroup();
|
||||
return Mathf.Max(1, currentLevelGroup.targetExtraWords); // Ensure it's at least 1 to prevent division by zero
|
||||
}
|
||||
|
||||
// Gets the current count of extra words found
|
||||
protected int GetCurrentExtraWordsCount()
|
||||
{
|
||||
return wordRepository.GetExtraWordsCount();
|
||||
}
|
||||
|
||||
// Calculate normalized progress as a value between 0 and 1
|
||||
protected float CalculateProgress(int current, int target)
|
||||
{
|
||||
return Mathf.Clamp01((float)current / target);
|
||||
}
|
||||
|
||||
// Updates the text display if available
|
||||
protected void UpdateTextDisplay(int currentValue, int targetValue)
|
||||
{
|
||||
if (progressText != null)
|
||||
{
|
||||
progressText.text = string.Format(textFormat, currentValue, targetValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c1c50d302d02427d9efaed58b590f731
|
||||
timeCreated: 1742318054
|
||||
@ -0,0 +1,63 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using WordsToolkit.Scripts.GUI.Buttons;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.ExtraWordBar
|
||||
{
|
||||
public class ImageExtraWordsProgressBar : BaseExtraWordsProgressBar
|
||||
{
|
||||
[Tooltip("Image component used as progress bar")]
|
||||
public Image progressBar;
|
||||
|
||||
[Tooltip("Speed of the fill animation (higher is faster)")]
|
||||
[Range(1f, 10f)]
|
||||
public float interpolationSpeed = 5f;
|
||||
|
||||
// Current displayed fill amount (for interpolation)
|
||||
private float _currentFill;
|
||||
|
||||
// Target fill amount we're interpolating toward
|
||||
private float _targetFill;
|
||||
[SerializeField]
|
||||
private ExtraWordsButton extraWordsButton;
|
||||
|
||||
protected override void UpdateProgressDisplay(float progress)
|
||||
{
|
||||
if (progressBar != null)
|
||||
{
|
||||
// Set the target fill amount instead of directly setting fillAmount
|
||||
_targetFill = progress;
|
||||
extraWordsButton.PulseAnimation(progress == 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// Smoothly interpolate the current fill amount towards the target
|
||||
if (progressBar != null && !Mathf.Approximately(_currentFill, _targetFill))
|
||||
{
|
||||
_currentFill = Mathf.Lerp(_currentFill, _targetFill, Time.deltaTime * interpolationSpeed);
|
||||
|
||||
// If we're very close to the target, snap to it
|
||||
if (Mathf.Abs(_currentFill - _targetFill) < 0.005f)
|
||||
{
|
||||
_currentFill = _targetFill;
|
||||
}
|
||||
|
||||
progressBar.fillAmount = _currentFill;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: afb2b6c16a9f44c5be59528504d23ca6
|
||||
timeCreated: 1742321446
|
||||
@ -0,0 +1,51 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.ExtraWordBar
|
||||
{
|
||||
public class SliderExtraWordsProgressBar : BaseExtraWordsProgressBar
|
||||
{
|
||||
[Tooltip("Slider component used as progress bar")]
|
||||
public Slider progressSlider;
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
// Configure the slider's min value
|
||||
if (progressSlider != null)
|
||||
{
|
||||
progressSlider.minValue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateProgressDisplay(float progress)
|
||||
{
|
||||
if (progressSlider != null)
|
||||
{
|
||||
progressSlider.value = PlayerPrefs.GetInt("ExtraWordsCollected");
|
||||
}
|
||||
}
|
||||
|
||||
// Apply max value changes to the slider component
|
||||
protected override void ApplyMaxValue()
|
||||
{
|
||||
if (progressSlider != null)
|
||||
{
|
||||
progressSlider.maxValue = maxValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0cb7c2a9625d4e8b964c8d627dfe1e43
|
||||
timeCreated: 1742321457
|
||||
20
Assets/WordConnectGameToolkit/Scripts/GUI/FXCanvas.cs
Normal file
20
Assets/WordConnectGameToolkit/Scripts/GUI/FXCanvas.cs
Normal file
@ -0,0 +1,20 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI
|
||||
{
|
||||
public class FXCanvas : MonoBehaviour
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b6413f9cec49418a89c0595be4a8f0e2
|
||||
timeCreated: 1730275156
|
||||
3
Assets/WordConnectGameToolkit/Scripts/GUI/Labels.meta
Normal file
3
Assets/WordConnectGameToolkit/Scripts/GUI/Labels.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 31b6dae04c644f229860c8c3d0ca1275
|
||||
timeCreated: 1725686154
|
||||
@ -0,0 +1,105 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
using WordsToolkit.Scripts.Gameplay.Pool;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Labels
|
||||
{
|
||||
public class CurrencyLabelAnimation : LabelAnim, ILabelAnimation
|
||||
{
|
||||
public void Animate(GameObject sourceObject, Vector3 startPosition, string rewardDataCount, AudioClip sound, Action callback)
|
||||
{
|
||||
var count = 0;
|
||||
var animateCount = 4;
|
||||
var targetPosition = targetTransform.transform.position;
|
||||
// if (coinsTextPrefab != null)
|
||||
// {
|
||||
// PopupText(startPosition, rewardDataCount);
|
||||
// }
|
||||
if (targetTransform)
|
||||
{
|
||||
for (var i = 0; i < animateCount; i++)
|
||||
{
|
||||
var item = GetAnimatedObjectSource(sourceObject);
|
||||
var random = .5f;
|
||||
item.transform.position = startPosition + new Vector3(Random.Range(-random, random), Random.Range(-random, random));
|
||||
var randomStartDelay = i==0? 0 : Random.Range(0f, 0.5f);
|
||||
StartAnim(item.transform, targetPosition, randomStartDelay, () =>
|
||||
{
|
||||
animatedObjectSource.ReleaseObject(item);
|
||||
if (doPunchScale == null || !doPunchScale.IsPlaying())
|
||||
{
|
||||
var punchScale = transform.DOPunchScale(Vector3.one * 0.2f, 0.2f);
|
||||
punchScale.OnComplete(() => { doPunchScale = null; });
|
||||
doPunchScale = punchScale;
|
||||
}
|
||||
|
||||
if (fxPrefab != null)
|
||||
{
|
||||
var fx = PoolObject.GetObject(fxPrefab, targetPosition);
|
||||
fx.transform.localScale = Vector3.one;
|
||||
fx.transform.position = targetPosition;
|
||||
DOVirtual.DelayedCall(1f, () => { PoolObject.Return(fx); });
|
||||
}
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
_audioService.PlaySound(sound);
|
||||
}
|
||||
|
||||
count++;
|
||||
if (count == animateCount)
|
||||
{
|
||||
transform.localScale = Vector3.one;
|
||||
callback?.Invoke();
|
||||
DOVirtual.DelayedCall(.5f, () => { DOTween.Kill(gameObject); });
|
||||
}
|
||||
|
||||
PoolObject.Return(item);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void StartAnim(Transform targetTransform, Vector3 targetPos, float randomStartDelay, Action callback = null)
|
||||
{
|
||||
var sequence = DOTween.Sequence();
|
||||
|
||||
targetTransform.localScale = Vector3.zero;
|
||||
var _scaleTween = targetTransform.DOScale(Vector3.one * 1f, .5f)
|
||||
.SetEase(Ease.OutBack)
|
||||
.SetDelay(randomStartDelay);
|
||||
|
||||
sequence.Append(_scaleTween);
|
||||
var _rotationTween = targetTransform.DORotate(new Vector3(0, 0, Random.Range(0, 360)), .3f)
|
||||
.SetEase(Ease.Linear)
|
||||
.SetLoops(1, LoopType.Incremental);
|
||||
|
||||
sequence.Join(_rotationTween);
|
||||
|
||||
var _movementTween = targetTransform.DOMove(targetPos, .3f)
|
||||
.SetEase(Ease.Linear)
|
||||
.OnComplete(() =>
|
||||
{
|
||||
callback?.Invoke();
|
||||
targetTransform.gameObject.SetActive(false);
|
||||
});
|
||||
|
||||
sequence.Join(_movementTween);
|
||||
sequence.Play();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70fae662836044c79412a304f4a5d3f3
|
||||
timeCreated: 1748447122
|
||||
@ -0,0 +1,104 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
using WordsToolkit.Scripts.Gameplay.Pool;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Labels
|
||||
{
|
||||
public class GemsLabelAnimation : LabelAnim, ILabelAnimation
|
||||
{
|
||||
public void Animate(GameObject sourceObject, Vector3 startPosition, string rewardDataCount, AudioClip sound, Action callback)
|
||||
{
|
||||
var count = 0;
|
||||
var animateCount = 4;
|
||||
var targetPosition = targetTransform.transform.position;
|
||||
// if (coinsTextPrefab != null)
|
||||
// {
|
||||
// PopupText(startPosition, rewardDataCount);
|
||||
// }
|
||||
if (targetTransform)
|
||||
{
|
||||
for (var i = 0; i < animateCount; i++)
|
||||
{
|
||||
var item = GetAnimatedObjectSource(sourceObject);
|
||||
var random = .5f;
|
||||
item.transform.position = startPosition + new Vector3(Random.Range(-random, random), Random.Range(-random, random));
|
||||
var randomStartDelay = i==0? 0 : Random.Range(0f, 0.5f);
|
||||
if (count == 0)
|
||||
{
|
||||
_audioService.PlayDelayed(sound, 1.0f);
|
||||
}
|
||||
StartAnim(item.transform, targetPosition, randomStartDelay, () =>
|
||||
{
|
||||
animatedObjectSource.ReleaseObject(item);
|
||||
if (doPunchScale == null || !doPunchScale.IsPlaying())
|
||||
{
|
||||
var punchScale = transform.DOPunchScale(Vector3.one * 0.2f, 0.2f);
|
||||
punchScale.OnComplete(() => { doPunchScale = null; });
|
||||
doPunchScale = punchScale;
|
||||
}
|
||||
|
||||
if (fxPrefab != null)
|
||||
{
|
||||
var fx = PoolObject.GetObject(fxPrefab, targetPosition);
|
||||
fx.transform.localScale = Vector3.one;
|
||||
fx.transform.position = targetPosition;
|
||||
DOVirtual.DelayedCall(1f, () => { PoolObject.Return(fx); });
|
||||
}
|
||||
|
||||
count++;
|
||||
if (count == animateCount)
|
||||
{
|
||||
transform.localScale = Vector3.one;
|
||||
callback?.Invoke();
|
||||
DOVirtual.DelayedCall(.5f, () => { DOTween.Kill(gameObject); });
|
||||
}
|
||||
|
||||
PoolObject.Return(item);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void StartAnim(Transform targetTransform, Vector3 targetPos, float randomStartDelay, Action callback = null)
|
||||
{
|
||||
var sequence = DOTween.Sequence();
|
||||
|
||||
targetTransform.localScale = Vector3.zero;
|
||||
var _scaleTween = targetTransform.DOScale(Vector3.one * 1f, .5f)
|
||||
.SetEase(Ease.OutBack)
|
||||
.SetDelay(randomStartDelay);
|
||||
|
||||
sequence.Append(_scaleTween);
|
||||
var _rotationTween = targetTransform.DORotate(new Vector3(0, 0, Random.Range(0, 360)), .3f)
|
||||
.SetEase(Ease.Linear)
|
||||
.SetLoops(1, LoopType.Incremental);
|
||||
|
||||
sequence.Join(_rotationTween);
|
||||
|
||||
var _movementTween = targetTransform.DOMove(targetPos, 0.5f)
|
||||
.SetEase(Ease.Linear)
|
||||
.OnComplete(() =>
|
||||
{
|
||||
callback?.Invoke();
|
||||
targetTransform.gameObject.SetActive(false);
|
||||
});
|
||||
|
||||
sequence.Append(_movementTween);
|
||||
sequence.Play();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5011c5819a984dbeac491d82a8128433
|
||||
timeCreated: 1749031939
|
||||
@ -0,0 +1,18 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Labels
|
||||
{
|
||||
public class HammerLabelAnimation : IconLabel
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 339d208ff02448daae7bbd7af2000c48
|
||||
timeCreated: 1748439618
|
||||
@ -0,0 +1,68 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.Pool;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Labels
|
||||
{
|
||||
public interface IAnimationSource
|
||||
{
|
||||
GameObject GetAnimatedObject();
|
||||
void ReleaseObject(GameObject animatedObject);
|
||||
}
|
||||
|
||||
public class PooledAnimationSource : IAnimationSource
|
||||
{
|
||||
private readonly ObjectPool<GameObject> _pool;
|
||||
|
||||
public PooledAnimationSource(GameObject prefab, Transform transform)
|
||||
{
|
||||
_pool = new ObjectPool<GameObject>(
|
||||
() => Object.Instantiate(prefab, transform),
|
||||
animatedObject => animatedObject.SetActive(true),
|
||||
animatedObject => animatedObject.SetActive(false),
|
||||
Object.Destroy
|
||||
);
|
||||
}
|
||||
|
||||
public GameObject GetAnimatedObject()
|
||||
{
|
||||
return _pool.Get();
|
||||
}
|
||||
|
||||
public void ReleaseObject(GameObject animatedObject)
|
||||
{
|
||||
_pool.Release(animatedObject);
|
||||
}
|
||||
}
|
||||
|
||||
public class SingleObjectAnimationSource : IAnimationSource
|
||||
{
|
||||
private readonly GameObject _animatedObject;
|
||||
|
||||
public SingleObjectAnimationSource(GameObject animatedObject)
|
||||
{
|
||||
_animatedObject = animatedObject;
|
||||
}
|
||||
|
||||
public GameObject GetAnimatedObject()
|
||||
{
|
||||
return _animatedObject;
|
||||
}
|
||||
|
||||
public void ReleaseObject(GameObject animatedObject)
|
||||
{
|
||||
animatedObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ad866880d5bd4e2a8c3bfe3bfb298d9c
|
||||
timeCreated: 1748509775
|
||||
@ -0,0 +1,23 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using WordsToolkit.Scripts.Popups.RewardsGift;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Labels
|
||||
{
|
||||
public interface ILabelAnimation
|
||||
{
|
||||
void Animate(GameObject sourceObject, Vector3 startPosition, string rewardDataCount, AudioClip sound, Action callback);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f7324cbdb7e04d8784e7b074ce95de5f
|
||||
timeCreated: 1748447755
|
||||
@ -0,0 +1,60 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
using WordsToolkit.Scripts.Gameplay.Pool;
|
||||
using WordsToolkit.Scripts.Popups.RewardsGift;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Labels
|
||||
{
|
||||
public class IconLabel : LabelAnim, ILabelAnimation
|
||||
{
|
||||
public void Animate(GameObject sourceObject, Vector3 startPosition, string rewardDataCount, AudioClip sound, Action callback)
|
||||
{
|
||||
sourceObject.GetComponent<GiftBase>().HideText();
|
||||
var animatedObject = GetAnimatedObjectSource(sourceObject);
|
||||
Vector3 targetPos = targetTransform.position;
|
||||
animatedObject.transform.position = startPosition;
|
||||
var sequence = DOTween.Sequence();
|
||||
var _decreaseScaleTween = animatedObject.transform.DOScale(Vector3.one * 0.1f, .3f)
|
||||
.SetEase(Ease.Linear);
|
||||
sequence.Join(_decreaseScaleTween);
|
||||
var _movementTween = animatedObject.transform.DOMove(targetPos, .3f)
|
||||
.SetEase(Ease.Linear);
|
||||
|
||||
sequence.Join(_movementTween);
|
||||
|
||||
// bounce after movement
|
||||
var _bounceTween = animatedObject.transform.DOScale(Vector3.one * .3f, .4f)
|
||||
.SetEase(Ease.OutBack)
|
||||
.OnComplete(() =>
|
||||
{
|
||||
_audioService.PlaySoundExclusive(sound);
|
||||
// play fx
|
||||
if (fxPrefab != null)
|
||||
{
|
||||
var fx = PoolObject.GetObject(fxPrefab, targetPos);
|
||||
fx.transform.position = targetPos;
|
||||
DOVirtual.DelayedCall(1f, () => { PoolObject.Return(fx); });
|
||||
}
|
||||
Release(animatedObject);
|
||||
callback?.Invoke();
|
||||
OnAnimationComplete?.Invoke();
|
||||
});
|
||||
sequence.Append(_bounceTween);
|
||||
|
||||
sequence.Play();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf51bcfa784c4a1ba25080cb5268d346
|
||||
timeCreated: 1748519904
|
||||
@ -0,0 +1,69 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using DG.Tweening;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using VContainer;
|
||||
using WordsToolkit.Scripts.Audio;
|
||||
using WordsToolkit.Scripts.Data;
|
||||
using WordsToolkit.Scripts.Gameplay.Pool;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Labels
|
||||
{
|
||||
public class LabelAnim : MonoBehaviour
|
||||
{
|
||||
public GameObject prefab;
|
||||
public Transform targetTransform;
|
||||
public ResourceObject associatedResource;
|
||||
|
||||
[SerializeField]
|
||||
protected GameObject fxPrefab;
|
||||
|
||||
[SerializeField]
|
||||
protected TextMeshProUGUI coinsTextPrefab;
|
||||
|
||||
protected Tweener doPunchScale;
|
||||
|
||||
[Inject]
|
||||
protected IAudioService _audioService;
|
||||
|
||||
protected IAnimationSource animatedObjectSource;
|
||||
|
||||
[SerializeField]
|
||||
protected UnityEvent OnAnimationComplete;
|
||||
protected GameObject GetAnimatedObjectSource(GameObject o)
|
||||
{
|
||||
animatedObjectSource ??= new PooledAnimationSource(o??prefab, transform);
|
||||
return animatedObjectSource.GetAnimatedObject();
|
||||
}
|
||||
|
||||
protected void Release(GameObject o)
|
||||
{
|
||||
animatedObjectSource?.ReleaseObject(o);
|
||||
}
|
||||
|
||||
protected void PopupText(Vector3 transformPosition, string rewardDataCount)
|
||||
{
|
||||
var coinsText = PoolObject.GetObject(coinsTextPrefab.gameObject, transformPosition).GetComponent<TextMeshProUGUI>();
|
||||
coinsText.transform.position = transformPosition;
|
||||
coinsText.text = rewardDataCount;
|
||||
coinsText.alpha = 0;
|
||||
|
||||
var sequence = DOTween.Sequence();
|
||||
sequence.Append(coinsText.DOFade(1, 0.2f));
|
||||
sequence.Join(coinsText.transform.DOMoveY(coinsText.transform.position.y + .5f, .5f)).OnComplete(() => { PoolObject.Return(coinsText.gameObject); });
|
||||
sequence.Append(coinsText.DOFade(0, 0.2f));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a33679f003442d482254fce1279dc4e
|
||||
timeCreated: 1722963833
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63234c9046ed647049b7a71f9237f61d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,50 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using WordsToolkit.Scripts.Data;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Labels
|
||||
{
|
||||
public static class ResourceAnimationController
|
||||
{
|
||||
public static void AnimateForResource(ResourceObject resourceObject, GameObject animatedObject, Vector3 startPosition, string rewardDataCount, AudioClip sound,
|
||||
Action callback)
|
||||
{
|
||||
var label = FindLabelForResource(resourceObject);
|
||||
if (label != null)
|
||||
{
|
||||
label.Animate(animatedObject, startPosition, rewardDataCount, sound, callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
callback?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
private static ILabelAnimation FindLabelForResource(ResourceObject resourceObject)
|
||||
{
|
||||
var allLabels = Object.FindObjectsOfType<LabelAnim>();
|
||||
foreach (var label in allLabels)
|
||||
{
|
||||
if (label.associatedResource == resourceObject)
|
||||
{
|
||||
return label as ILabelAnimation;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a27ac2d882a446c38e9418f664e5238e
|
||||
timeCreated: 1748412719
|
||||
@ -0,0 +1,42 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using WordsToolkit.Scripts.Data;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Labels
|
||||
{
|
||||
public class ResourceLabel : MonoBehaviour
|
||||
{
|
||||
public ResourceObject resourceObject;
|
||||
|
||||
[SerializeField]
|
||||
private TextMeshProUGUI text;
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
resourceObject.OnResourceUpdate += UpdateValue;
|
||||
UpdateValue(resourceObject.GetValue());
|
||||
}
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
resourceObject.OnResourceUpdate -= UpdateValue;
|
||||
}
|
||||
|
||||
protected virtual void UpdateValue(int count)
|
||||
{
|
||||
text.text = count.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c79bf792c0d841e59f4e9ce0e4f13cc8
|
||||
timeCreated: 1716450501
|
||||
@ -0,0 +1,18 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Labels
|
||||
{
|
||||
public class TipLabelAnimation : IconLabel
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 996433fa960e41578e8420db55d6317f
|
||||
timeCreated: 1748439593
|
||||
@ -0,0 +1,75 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using VContainer;
|
||||
using WordsToolkit.Scripts.Enums;
|
||||
using WordsToolkit.Scripts.Gameplay.Managers;
|
||||
using WordsToolkit.Scripts.GUI.Buttons;
|
||||
using WordsToolkit.Scripts.Levels;
|
||||
using WordsToolkit.Scripts.Localization;
|
||||
using WordsToolkit.Scripts.Popups;
|
||||
using WordsToolkit.Scripts.Services;
|
||||
using WordsToolkit.Scripts.System;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI
|
||||
{
|
||||
public class LanguageSelectionButton : MonoBehaviour
|
||||
{
|
||||
public TextMeshProUGUI languageText;
|
||||
public CustomButton button;
|
||||
[Inject]
|
||||
private StateManager stateManager;
|
||||
[Inject]
|
||||
private MenuManager menuManager;
|
||||
[Inject]
|
||||
private ILanguageService languageService;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
button.onClick.AddListener(OnClick);
|
||||
languageText.text = LocalizationManager.instance.GetLocalizedCurrentLanguage();
|
||||
EventManager.GetEvent<string>(EGameEvent.LanguageChanged).Subscribe(OnLanguageChanged);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
button.onClick.RemoveListener(OnClick);
|
||||
EventManager.GetEvent<string>(EGameEvent.LanguageChanged).Unsubscribe(OnLanguageChanged);
|
||||
}
|
||||
|
||||
private void OnLanguageChanged(string obj)
|
||||
{
|
||||
UpdateText();
|
||||
}
|
||||
|
||||
private void UpdateText()
|
||||
{
|
||||
languageText.text = LocalizationManager.instance.GetLocalizedCurrentLanguage();
|
||||
}
|
||||
|
||||
private void OnClick()
|
||||
{
|
||||
ShowLanguageSelector();
|
||||
}
|
||||
|
||||
public void ShowLanguageSelector()
|
||||
{
|
||||
menuManager.CloseAllPopups();
|
||||
menuManager.ShowPopup<LanguageSelectionGame>(null, result =>
|
||||
{
|
||||
UpdateText();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce23d940581c42ddb21ae9b4c053a1fb
|
||||
timeCreated: 1742713425
|
||||
@ -0,0 +1,43 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI
|
||||
{
|
||||
public class LanguageSelectionElement : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private TextMeshProUGUI languageName;
|
||||
[SerializeField]
|
||||
private GameObject checkMark;
|
||||
[SerializeField]
|
||||
private GameObject selectedBackground;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
SetCheckMarkActive(false);
|
||||
}
|
||||
|
||||
public void SetLanguageName(string name)
|
||||
{
|
||||
languageName.text = name;
|
||||
}
|
||||
|
||||
public void SetCheckMarkActive(bool isActive)
|
||||
{
|
||||
checkMark.SetActive(isActive);
|
||||
selectedBackground.SetActive(isActive);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34f6491ebc5f45a48522da26ec0beb4d
|
||||
timeCreated: 1742718301
|
||||
@ -0,0 +1,191 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using VContainer;
|
||||
using VContainer.Unity;
|
||||
using WordsToolkit.Scripts.Enums;
|
||||
using WordsToolkit.Scripts.GUI.Buttons;
|
||||
using WordsToolkit.Scripts.Levels;
|
||||
using WordsToolkit.Scripts.Localization;
|
||||
using WordsToolkit.Scripts.Popups;
|
||||
using WordsToolkit.Scripts.Services;
|
||||
using WordsToolkit.Scripts.System;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI
|
||||
{
|
||||
public class LanguageSelectionGame : Popup
|
||||
{
|
||||
private List<LanguageConfiguration.LanguageInfo> languages;
|
||||
[SerializeField] private LanguageSelectionElement languageButtonPrefab;
|
||||
[SerializeField] private Transform languageButtonContainer;
|
||||
[SerializeField] private ScrollRect scrollView;
|
||||
[SerializeField] private TextMeshProUGUI selectedLanguageText;
|
||||
public CurtureTuple[] extraLanguages;
|
||||
[SerializeField]
|
||||
private LanguageConfiguration languageConfiguration;
|
||||
|
||||
[Inject]
|
||||
private ILanguageService languageService;
|
||||
|
||||
private Button[] languageButtons;
|
||||
private int currentSelectedIndex = -1;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Check for layout component on container
|
||||
if (languageButtonContainer.GetComponent<LayoutGroup>() == null)
|
||||
{
|
||||
Debug.LogWarning("No LayoutGroup component found on languageButtonContainer. Elements may overlap.");
|
||||
}
|
||||
|
||||
// Get enabled languages from configuration
|
||||
languages = languageConfiguration.GetEnabledLanguages();
|
||||
|
||||
// Add extra languages if configured
|
||||
if (extraLanguages != null && extraLanguages.Length > 0)
|
||||
{
|
||||
foreach (var extraLang in extraLanguages)
|
||||
{
|
||||
var langInfo = languageConfiguration.GetLanguageInfo(extraLang.culture);
|
||||
if (langInfo != null && !languages.Contains(langInfo))
|
||||
{
|
||||
languages.Add(langInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LocalizationManager.instance.InitializeLocalization();
|
||||
PopulateLanguageButtons();
|
||||
}
|
||||
|
||||
private void PopulateLanguageButtons()
|
||||
{
|
||||
// Clear existing buttons if any
|
||||
foreach (Transform child in languageButtonContainer)
|
||||
{
|
||||
Destroy(child.gameObject);
|
||||
}
|
||||
|
||||
var currentLanguageCode = languageService.GetCurrentLanguageCode();
|
||||
currentSelectedIndex = languages.FindIndex(l => l.code == currentLanguageCode);
|
||||
|
||||
languageButtons = new Button[languages.Count];
|
||||
|
||||
for (int i = 0; i < languages.Count; i++)
|
||||
{
|
||||
var buttonObj = _container.Instantiate(languageButtonPrefab, languageButtonContainer);
|
||||
var button = buttonObj.GetComponent<CustomButton>();
|
||||
buttonObj.SetLanguageName(languages[i].localizedName.ToUpper());
|
||||
|
||||
// Ensure proper positioning in layout
|
||||
RectTransform rectTransform = buttonObj.GetComponent<RectTransform>();
|
||||
rectTransform.localScale = Vector3.one;
|
||||
|
||||
int index = i; // Capture the index for the lambda
|
||||
button.onClick.AddListener(() =>
|
||||
{
|
||||
SelectLanguage(index);
|
||||
});
|
||||
|
||||
languageButtons[i] = button;
|
||||
// if the language is selected, set the checkmark active
|
||||
buttonObj.SetCheckMarkActive(i == currentSelectedIndex);
|
||||
}
|
||||
|
||||
// Force layout rebuild
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(languageButtonContainer.GetComponent<RectTransform>());
|
||||
Canvas.ForceUpdateCanvases();
|
||||
|
||||
// Make sure the content size fitter is updated if present
|
||||
if (languageButtonContainer.GetComponent<ContentSizeFitter>() != null)
|
||||
{
|
||||
languageButtonContainer.GetComponent<ContentSizeFitter>().SetLayoutVertical();
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectLanguage(int index)
|
||||
{
|
||||
if (index < 0 || index >= languages.Count)
|
||||
return;
|
||||
|
||||
// First deactivate all checkmarks
|
||||
for (int i = 0; i < languageButtons.Length; i++)
|
||||
{
|
||||
if (languageButtons[i].GetComponent<LanguageSelectionElement>() != null)
|
||||
{
|
||||
languageButtons[i].GetComponent<LanguageSelectionElement>().SetCheckMarkActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Then activate only the selected one
|
||||
if (languageButtons[index].GetComponent<LanguageSelectionElement>() != null)
|
||||
{
|
||||
languageButtons[index].GetComponent<LanguageSelectionElement>().SetCheckMarkActive(true);
|
||||
}
|
||||
|
||||
// Update visual selection
|
||||
if (currentSelectedIndex >= 0 && currentSelectedIndex < languageButtons.Length)
|
||||
{
|
||||
// Reset previous selection visual if needed
|
||||
ColorBlock colors = languageButtons[currentSelectedIndex].colors;
|
||||
colors.normalColor = Color.white;
|
||||
languageButtons[currentSelectedIndex].colors = colors;
|
||||
}
|
||||
|
||||
currentSelectedIndex = index;
|
||||
|
||||
// Scroll to the selected button
|
||||
Canvas.ForceUpdateCanvases();
|
||||
|
||||
var selectedLanguage = languages[index];
|
||||
|
||||
// Use LanguageService to set the language
|
||||
languageService.SetLanguage(selectedLanguage.code);
|
||||
|
||||
// find all objects of LocalizationTextMeshProUGUI
|
||||
var localizationTextObjects = FindObjectsOfType<LocalizedTextMeshProUGUI>();
|
||||
foreach (var localizationText in localizationTextObjects)
|
||||
{
|
||||
localizationText.UpdateText();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnChangeLanguage()
|
||||
{
|
||||
if (currentSelectedIndex >= 0)
|
||||
{
|
||||
var selectedLanguage = languages[currentSelectedIndex];
|
||||
if (selectedLanguage.localizationBase != null)
|
||||
{
|
||||
LocalizationManager.instance.LoadLanguageFromBase(selectedLanguage.localizationBase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private LanguageConfiguration.LanguageInfo GetSelectedLanguage()
|
||||
{
|
||||
return languages[currentSelectedIndex];
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct CurtureTuple
|
||||
{
|
||||
public string culture;
|
||||
public string name;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 683caedab150f4458b1d44042dc202f1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
53
Assets/WordConnectGameToolkit/Scripts/GUI/NoAdsButton.cs
Normal file
53
Assets/WordConnectGameToolkit/Scripts/GUI/NoAdsButton.cs
Normal file
@ -0,0 +1,53 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
using WordsToolkit.Scripts.Popups;
|
||||
using WordsToolkit.Scripts.System;
|
||||
using VContainer;
|
||||
using WordsToolkit.Scripts.GUI.Buttons;
|
||||
using WordsToolkit.Scripts.Services;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI
|
||||
{
|
||||
public class NoAdsButton : CustomButton
|
||||
{
|
||||
[Inject]
|
||||
private MenuManager menuManager;
|
||||
|
||||
[Inject]
|
||||
private GameManager gameManager;
|
||||
|
||||
[Inject]
|
||||
private IAdsManager adsManager;
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
if (adsManager != null && adsManager.IsNoAdsPurchased())
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
onClick.AddListener(() =>
|
||||
{
|
||||
menuManager.CloseAllPopups();
|
||||
DOVirtual.DelayedCall(0.5f, () =>
|
||||
{
|
||||
gameManager.RemoveAds();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 38cf47ea73764d40996e1d8445fdec1c
|
||||
timeCreated: 1726470327
|
||||
33
Assets/WordConnectGameToolkit/Scripts/GUI/OutlineField.cs
Normal file
33
Assets/WordConnectGameToolkit/Scripts/GUI/OutlineField.cs
Normal file
@ -0,0 +1,33 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI
|
||||
{
|
||||
public class OutlineField : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private Image imageToFade;
|
||||
|
||||
[SerializeField]
|
||||
private Image imageToFade2;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
imageToFade.DOFade(.5f, .5f).SetLoops(-1, LoopType.Yoyo);
|
||||
imageToFade2.DOFade(.5f, .5f).SetLoops(-1, LoopType.Yoyo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68b5702063f7452fb8347a9e17336c1c
|
||||
timeCreated: 1728481029
|
||||
76
Assets/WordConnectGameToolkit/Scripts/GUI/SafeArea.cs
Normal file
76
Assets/WordConnectGameToolkit/Scripts/GUI/SafeArea.cs
Normal file
@ -0,0 +1,76 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI
|
||||
{
|
||||
[ExecuteAlways]
|
||||
public class SafeArea : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private RectTransform rectCanvasTransform;
|
||||
|
||||
private Rect lastSafeArea = Rect.zero;
|
||||
private Vector2 lastScreenSize = Vector2.zero;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
ApplySafeArea();
|
||||
}
|
||||
|
||||
private void OnRectTransformDimensionsChange()
|
||||
{
|
||||
ApplySafeArea();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
ApplySafeArea();
|
||||
}
|
||||
#endif
|
||||
|
||||
private void ApplySafeArea()
|
||||
{
|
||||
if (rectCanvasTransform == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var safeArea = Screen.safeArea;
|
||||
var screenSize = new Vector2(Screen.width, Screen.height);
|
||||
if (safeArea != lastSafeArea || screenSize != lastScreenSize)
|
||||
{
|
||||
lastSafeArea = safeArea;
|
||||
lastScreenSize = screenSize;
|
||||
|
||||
var anchorMin = safeArea.position;
|
||||
var anchorMax = safeArea.position + safeArea.size;
|
||||
|
||||
if (screenSize.x == 0 || screenSize.y == 0)
|
||||
{
|
||||
Debug.LogError($"Screen size is zero: {screenSize}");
|
||||
return;
|
||||
}
|
||||
|
||||
anchorMin.x /= screenSize.x;
|
||||
anchorMin.y /= screenSize.y;
|
||||
anchorMax.x /= screenSize.x;
|
||||
anchorMax.y /= screenSize.y;
|
||||
|
||||
rectCanvasTransform.anchorMin = anchorMin;
|
||||
rectCanvasTransform.anchorMax = anchorMax;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a662ae09fc7e48e38df93e3acf55ed59
|
||||
timeCreated: 1725705596
|
||||
192
Assets/WordConnectGameToolkit/Scripts/GUI/TimerDisplay.cs
Normal file
192
Assets/WordConnectGameToolkit/Scripts/GUI/TimerDisplay.cs
Normal file
@ -0,0 +1,192 @@
|
||||
using DG.Tweening;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using VContainer;
|
||||
using WordsToolkit.Scripts.Audio;
|
||||
using WordsToolkit.Scripts.Gameplay.Managers;
|
||||
using WordsToolkit.Scripts.Utils;
|
||||
using WordsToolkit.Scripts.System;
|
||||
using WordsToolkit.Scripts.Enums;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI
|
||||
{
|
||||
[RequireComponent(typeof(TextMeshProUGUI))]
|
||||
public class TimerDisplay : MonoBehaviour
|
||||
{
|
||||
private TextMeshProUGUI timerText;
|
||||
[Inject]
|
||||
private LevelManager levelManager;
|
||||
[Inject]
|
||||
private IAudioService audioService;
|
||||
private CanvasGroup canvasGroup;
|
||||
private Color originalTextColor;
|
||||
[SerializeField]
|
||||
private AudioClip alertSound;
|
||||
|
||||
private Sequence bounceSequence;
|
||||
private Sequence fadeSequence;
|
||||
private bool isWarningActive;
|
||||
private bool isVisible = true;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
timerText = GetComponent<TextMeshProUGUI>();
|
||||
canvasGroup = GetComponent<CanvasGroup>();
|
||||
|
||||
// Add canvas group if it doesn't exist
|
||||
if (canvasGroup == null)
|
||||
canvasGroup = gameObject.AddComponent<CanvasGroup>();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
originalTextColor = timerText.color;
|
||||
EventManager.OnGameStateChanged += OnGameStateChanged;
|
||||
UpdateVisibility();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
EventManager.OnGameStateChanged -= OnGameStateChanged;
|
||||
|
||||
if (bounceSequence != null)
|
||||
{
|
||||
bounceSequence.Kill();
|
||||
bounceSequence = null;
|
||||
}
|
||||
|
||||
if (fadeSequence != null)
|
||||
{
|
||||
fadeSequence.Kill();
|
||||
fadeSequence = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (levelManager != null && isVisible)
|
||||
{
|
||||
float timeToDisplay;
|
||||
bool isTimerActive = levelManager.HasTimer;
|
||||
|
||||
// Update timer text - display as countdown
|
||||
if (levelManager.HasTimer && levelManager.TimerLimit > 0)
|
||||
{
|
||||
// Calculate remaining time
|
||||
float remainingTime = Mathf.Max(0, levelManager.TimerLimit - levelManager.GameTime);
|
||||
timerText.text = TimeUtils.GetTimeString(remainingTime);
|
||||
timeToDisplay = remainingTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
// For timers without limits, just show elapsed time
|
||||
timerText.text = TimeUtils.GetTimeString(levelManager.GameTime);
|
||||
timeToDisplay = levelManager.GameTime;
|
||||
}
|
||||
|
||||
if (timeToDisplay <= 10f && !isWarningActive && isTimerActive)
|
||||
{
|
||||
StartWarningEffect();
|
||||
}
|
||||
else if (timeToDisplay > 10f && isWarningActive)
|
||||
{
|
||||
StopWarningEffect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGameStateChanged(EGameState newState)
|
||||
{
|
||||
UpdateVisibility();
|
||||
}
|
||||
|
||||
private void UpdateVisibility()
|
||||
{
|
||||
bool shouldBeVisible = levelManager.HasTimer && EventManager.GameStatus <= EGameState.Playing;
|
||||
|
||||
if (shouldBeVisible && !isVisible)
|
||||
{
|
||||
ShowTimer();
|
||||
}
|
||||
else if (!shouldBeVisible && isVisible)
|
||||
{
|
||||
HideTimer();
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowTimer()
|
||||
{
|
||||
if (fadeSequence != null)
|
||||
{
|
||||
fadeSequence.Kill();
|
||||
fadeSequence = null;
|
||||
}
|
||||
|
||||
isVisible = true;
|
||||
canvasGroup.interactable = true;
|
||||
canvasGroup.blocksRaycasts = true;
|
||||
|
||||
fadeSequence = DOTween.Sequence();
|
||||
fadeSequence.Append(canvasGroup.DOFade(1f, 0.3f));
|
||||
}
|
||||
|
||||
private void HideTimer()
|
||||
{
|
||||
if (fadeSequence != null)
|
||||
{
|
||||
fadeSequence.Kill();
|
||||
fadeSequence = null;
|
||||
}
|
||||
|
||||
isVisible = false;
|
||||
|
||||
fadeSequence = DOTween.Sequence();
|
||||
fadeSequence.Append(canvasGroup.DOFade(0f, 0.5f));
|
||||
fadeSequence.OnComplete(() =>
|
||||
{
|
||||
canvasGroup.interactable = false;
|
||||
canvasGroup.blocksRaycasts = false;
|
||||
});
|
||||
}
|
||||
|
||||
private void StartWarningEffect()
|
||||
{
|
||||
if (timerText == null) return;
|
||||
|
||||
if (alertSound != null)
|
||||
audioService.PlaySound(alertSound);
|
||||
|
||||
isWarningActive = true;
|
||||
originalTextColor = timerText.color;
|
||||
|
||||
if (bounceSequence != null)
|
||||
{
|
||||
bounceSequence.Kill();
|
||||
bounceSequence = null;
|
||||
}
|
||||
|
||||
bounceSequence = DOTween.Sequence();
|
||||
bounceSequence.Append(timerText.transform.DOScale(1.2f, 0.3f));
|
||||
bounceSequence.Append(timerText.transform.DOScale(1f, 0.3f));
|
||||
timerText.color = new Color32(0xF6, 0x42, 0x8E, 0xFF);
|
||||
bounceSequence.SetLoops(-1);
|
||||
}
|
||||
|
||||
private void StopWarningEffect()
|
||||
{
|
||||
if (timerText == null) return;
|
||||
|
||||
isWarningActive = false;
|
||||
|
||||
if (bounceSequence != null)
|
||||
{
|
||||
bounceSequence.Kill();
|
||||
bounceSequence = null;
|
||||
}
|
||||
|
||||
timerText.transform.localScale = Vector3.one;
|
||||
timerText.color = originalTextColor;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: abccc317893fb4c2182dfcf18f02729c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
3
Assets/WordConnectGameToolkit/Scripts/GUI/Tutorials.meta
Normal file
3
Assets/WordConnectGameToolkit/Scripts/GUI/Tutorials.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2ae417f18304616bd2f3c81783575b2
|
||||
timeCreated: 1748527886
|
||||
@ -0,0 +1,18 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Tutorials
|
||||
{
|
||||
public class TutorialExtraWords : TutorialPopupUI
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7d3fb59d92c40efa3b8e25774fd7ed2
|
||||
timeCreated: 1748240603
|
||||
@ -0,0 +1,66 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using UnityEngine;
|
||||
using WordsToolkit.Scripts.Localization;
|
||||
using WordsToolkit.Scripts.Popups;
|
||||
using WordsToolkit.Scripts.Settings;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Tutorials
|
||||
{
|
||||
public class TutorialPopupBase : Popup
|
||||
{
|
||||
[SerializeField]
|
||||
private LocalizedTextMeshProUGUI text;
|
||||
|
||||
protected TutorialSettingsData tutorialData;
|
||||
|
||||
protected GameObject[] GetObjectsOfTagsToShow()
|
||||
{
|
||||
if (tagsToShow == null || tagsToShow.Length == 0)
|
||||
return null;
|
||||
|
||||
var tags = new GameObject[tagsToShow.Length];
|
||||
for (int i = 0; i < tagsToShow.Length; i++)
|
||||
{
|
||||
var t = GameObject.FindGameObjectWithTag(tagsToShow[i]);
|
||||
if (t == null)
|
||||
Debug.LogError($"TutorialPopupBase: GetTagsToShow: {tagsToShow[i]} found: {t != null}");
|
||||
if (t != null)
|
||||
{
|
||||
tags[i] = t;
|
||||
}
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
public void SetTitle(string getText)
|
||||
{
|
||||
if (text != null)
|
||||
{
|
||||
text.text = getText;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetData(TutorialSettingsData tutorialData)
|
||||
{
|
||||
this.tutorialData = tutorialData;
|
||||
ShowTags(tutorialData.tagsToShow);
|
||||
}
|
||||
|
||||
public TutorialSettingsData GetData()
|
||||
{
|
||||
return tutorialData;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62879301cce14e229585844c2d2e1d5e
|
||||
timeCreated: 1748157756
|
||||
@ -0,0 +1,45 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
using VContainer;
|
||||
using WordsToolkit.Scripts.Enums;
|
||||
using WordsToolkit.Scripts.Gameplay;
|
||||
using WordsToolkit.Scripts.Gameplay.Managers;
|
||||
using WordsToolkit.Scripts.System;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Tutorials
|
||||
{
|
||||
public class TutorialPopupGame : TutorialWordSubstitution
|
||||
{
|
||||
public override void AfterShowAnimation()
|
||||
{
|
||||
base.AfterShowAnimation();
|
||||
var words = levelManager.GetCurrentLevel().GetWords(gameManager.language);
|
||||
ReplaceWordForTutorial(words[0]);
|
||||
SelectWordAnimation(words[0]);
|
||||
var tiles = fieldManager.GetTilesWord(words[0]);
|
||||
if (tiles != null && tiles.Count > 0)
|
||||
{
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
if (tile != null)
|
||||
{
|
||||
MakeObjectVisible(tile.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71d0ca3b60b74d44bcff8d7f94a91ac8
|
||||
timeCreated: 1748156902
|
||||
@ -0,0 +1,95 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Tutorials
|
||||
{
|
||||
public class TutorialPopupUI : TutorialPopupBase
|
||||
{
|
||||
[SerializeField]
|
||||
protected GameObject arrow;
|
||||
|
||||
protected Coroutine arrowAnimation;
|
||||
protected GameObject targetObject;
|
||||
protected float arrowOffset = 1.0f;
|
||||
|
||||
public override void AfterShowAnimation()
|
||||
{
|
||||
base.AfterShowAnimation();
|
||||
|
||||
targetObject = GetObjectsOfTagsToShow()[0];
|
||||
if (targetObject != null && arrow != null)
|
||||
{
|
||||
Vector3 targetPos = targetObject.transform.position;
|
||||
if (targetPos.x < 0)
|
||||
{
|
||||
arrow.transform.localScale = new Vector3(-1, 1, 1);
|
||||
arrowOffset = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
arrow.transform.localScale = new Vector3(1, 1, 1);
|
||||
arrowOffset = -1.0f;
|
||||
}
|
||||
|
||||
UpdateArrowPosition();
|
||||
arrow.SetActive(true);
|
||||
arrowAnimation = StartCoroutine(AnimateArrow());
|
||||
}
|
||||
}
|
||||
|
||||
protected void UpdateArrowPosition()
|
||||
{
|
||||
if (targetObject != null && arrow != null)
|
||||
{
|
||||
Vector3 targetPos = targetObject.transform.position;
|
||||
arrow.transform.position = new Vector3(targetPos.x + arrowOffset, targetPos.y, targetPos.z);
|
||||
}
|
||||
}
|
||||
|
||||
protected IEnumerator AnimateArrow()
|
||||
{
|
||||
float time = 0f;
|
||||
float wobbleAmount = 0.1f;
|
||||
|
||||
while (true)
|
||||
{
|
||||
time += Time.deltaTime * 2f; // Complete one cycle in 0.5 seconds
|
||||
UpdateArrowPosition();
|
||||
|
||||
// Add small wobble animation
|
||||
float wobble = Mathf.PingPong(time, 1f) * wobbleAmount;
|
||||
Vector3 currentPos = arrow.transform.position;
|
||||
arrow.transform.position = new Vector3(currentPos.x + (arrowOffset > 0 ? wobble : -wobble), currentPos.y, currentPos.z);
|
||||
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void AfterHideAnimation()
|
||||
{
|
||||
base.AfterHideAnimation();
|
||||
if (arrow != null)
|
||||
{
|
||||
arrow.SetActive(false);
|
||||
if (arrowAnimation != null)
|
||||
{
|
||||
StopCoroutine(arrowAnimation);
|
||||
arrowAnimation = null;
|
||||
}
|
||||
}
|
||||
targetObject = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2fb722bb3ee846c9b50fb4fdd88276d1
|
||||
timeCreated: 1748086797
|
||||
@ -0,0 +1,36 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Tutorials
|
||||
{
|
||||
public class TutorialRedGem : TutorialWordSubstitution
|
||||
{
|
||||
public override void AfterShowAnimation()
|
||||
{
|
||||
base.AfterShowAnimation();
|
||||
var tiles = fieldManager.GetTilesWordWithSpecialItems(out var word);
|
||||
ReplaceWordForTutorial(word);
|
||||
SelectWordAnimation(word);
|
||||
// make tiles above UI
|
||||
if (tiles != null && tiles.Count > 0)
|
||||
{
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
if (tile != null)
|
||||
{
|
||||
MakeObjectVisible(tile.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c69baf91b6764c6d9e5a061a9ca87959
|
||||
timeCreated: 1748266655
|
||||
@ -0,0 +1,32 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Tutorials
|
||||
{
|
||||
public class TutorialTime : TutorialPopupUI
|
||||
{
|
||||
public override void AfterShowAnimation()
|
||||
{
|
||||
base.AfterShowAnimation();
|
||||
|
||||
targetObject = GetObjectsOfTagsToShow()[0];
|
||||
if (targetObject != null && arrow != null)
|
||||
{
|
||||
UpdateArrowPosition();
|
||||
arrow.SetActive(true);
|
||||
arrowAnimation = StartCoroutine(AnimateArrow());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08a2702beacc4f3eae33f19c8558a0c1
|
||||
timeCreated: 1750149586
|
||||
@ -0,0 +1,88 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
using VContainer;
|
||||
using WordsToolkit.Scripts.Enums;
|
||||
using WordsToolkit.Scripts.Gameplay;
|
||||
using WordsToolkit.Scripts.Gameplay.Managers;
|
||||
using WordsToolkit.Scripts.System;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI.Tutorials
|
||||
{
|
||||
public class TutorialWordSubstitution : TutorialPopupBase
|
||||
{
|
||||
[Inject]
|
||||
protected LevelManager levelManager;
|
||||
|
||||
[Inject]
|
||||
protected GameManager gameManager;
|
||||
|
||||
[SerializeField]
|
||||
private GameObject hand;
|
||||
|
||||
protected void ReplaceWordForTutorial(string word)
|
||||
{
|
||||
localizationManager.SetPairPlaceholder("word", word.ToUpper());
|
||||
SetTitle(localizationManager.GetText(tutorialData.kind.ToString(), "Tutorial"));
|
||||
}
|
||||
|
||||
protected void SelectWordAnimation(string wordForTutorial)
|
||||
{
|
||||
var selection = FindObjectOfType<WordSelectionManager>();
|
||||
var letters = selection.GetLetters(wordForTutorial);
|
||||
AnimateHandToLetters(letters);
|
||||
EventManager.GetEvent<string>(EGameEvent.WordOpened).Subscribe(OnWordOpened);
|
||||
}
|
||||
|
||||
private void OnWordOpened(string obj)
|
||||
{
|
||||
EventManager.GetEvent<string>(EGameEvent.WordOpened).Unsubscribe(OnWordOpened);
|
||||
Close();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (hand != null)
|
||||
{
|
||||
hand.SetActive(false);
|
||||
hand.transform.DOKill();
|
||||
}
|
||||
}
|
||||
|
||||
private void AnimateHandToLetters(List<LetterButton> letters)
|
||||
{
|
||||
var path = new List<Vector3>();
|
||||
foreach (var letter in letters)
|
||||
{
|
||||
// Skip null letters (in case a word can't be formed with available letters)
|
||||
if (letter != null)
|
||||
{
|
||||
path.Add(letter.transform.position + new Vector3(.5f, -0.8f, 0)); // Adjusting position to avoid overlap with letter
|
||||
}
|
||||
}
|
||||
if (path.Count > 0)
|
||||
{
|
||||
if (hand != null)
|
||||
{
|
||||
hand.SetActive(true);
|
||||
hand.transform.position = path[0];
|
||||
hand.transform.DOPath(path.ToArray(), 2f, PathType.CatmullRom)
|
||||
.SetEase(Ease.InOutSine)
|
||||
.SetLoops(-1, LoopType.Restart);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 47831d486a4f4d869ae4809e05afb516
|
||||
timeCreated: 1748532563
|
||||
111
Assets/WordConnectGameToolkit/Scripts/GUI/UILineRenderer.cs
Normal file
111
Assets/WordConnectGameToolkit/Scripts/GUI/UILineRenderer.cs
Normal file
@ -0,0 +1,111 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI
|
||||
{
|
||||
[RequireComponent(typeof(CanvasRenderer))]
|
||||
public class UILineRenderer : MaskableGraphic
|
||||
{
|
||||
public Vector2[] _points;
|
||||
public Vector2[] points
|
||||
{
|
||||
get => _points;
|
||||
set
|
||||
{
|
||||
_points = value;
|
||||
SetVerticesDirty(); // Tell Unity to redraw the UI component
|
||||
}
|
||||
}
|
||||
|
||||
public float thickness = 10f;
|
||||
public bool center = true;
|
||||
|
||||
protected override void OnPopulateMesh(VertexHelper vh)
|
||||
{
|
||||
vh.Clear();
|
||||
|
||||
if (_points == null || _points.Length < 2)
|
||||
return;
|
||||
for (int i = 0; i < _points.Length-1; i++)
|
||||
{
|
||||
// Create a line segment between the next two points
|
||||
CreateLineSegment(_points[i], _points[i+1], vh);
|
||||
|
||||
int index = i * 5;
|
||||
|
||||
// Add the line segment to the triangles array
|
||||
vh.AddTriangle(index, index+1, index+3);
|
||||
vh.AddTriangle(index+3, index+2, index);
|
||||
|
||||
// These two triangles create the beveled edges
|
||||
// between line segments using the end point of
|
||||
// the last line segment and the start points of this one
|
||||
if (i != 0)
|
||||
{
|
||||
vh.AddTriangle(index, index-1, index-3);
|
||||
vh.AddTriangle(index+1, index-1, index-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a rect from two points that acts as a line segment
|
||||
/// </summary>
|
||||
/// <param name="point1">The starting point of the segment</param>
|
||||
/// <param name="point2">The endint point of the segment</param>
|
||||
/// <param name="vh">The vertex helper that the segment is added to</param>
|
||||
private void CreateLineSegment(Vector3 point1, Vector3 point2, VertexHelper vh)
|
||||
{
|
||||
Vector3 offset = center ? (rectTransform.sizeDelta / 2) : Vector2.zero;
|
||||
|
||||
// Create vertex template
|
||||
UIVertex vertex = UIVertex.simpleVert;
|
||||
vertex.color = color;
|
||||
|
||||
// Create the start of the segment
|
||||
Quaternion point1Rotation = Quaternion.Euler(0, 0, RotatePointTowards(point1, point2) + 90);
|
||||
vertex.position = point1Rotation * new Vector3(-thickness / 2, 0);
|
||||
vertex.position += point1 - offset;
|
||||
vh.AddVert(vertex);
|
||||
vertex.position = point1Rotation * new Vector3(thickness / 2, 0);
|
||||
vertex.position += point1 - offset;
|
||||
vh.AddVert(vertex);
|
||||
|
||||
// Create the end of the segment
|
||||
Quaternion point2Rotation = Quaternion.Euler(0, 0, RotatePointTowards(point2, point1) - 90);
|
||||
vertex.position = point2Rotation * new Vector3(-thickness / 2, 0);
|
||||
vertex.position += point2 - offset;
|
||||
vh.AddVert(vertex);
|
||||
vertex.position = point2Rotation * new Vector3(thickness / 2, 0);
|
||||
vertex.position += point2 - offset;
|
||||
vh.AddVert(vertex);
|
||||
|
||||
// Also add the end point
|
||||
vertex.position = point2 - offset;
|
||||
vh.AddVert(vertex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the angle that a vertex needs to rotate to face target vertex
|
||||
/// </summary>
|
||||
/// <param name="vertex">The vertex being rotated</param>
|
||||
/// <param name="target">The vertex to rotate towards</param>
|
||||
/// <returns>The angle required to rotate vertex towards target</returns>
|
||||
private float RotatePointTowards(Vector2 vertex, Vector2 target)
|
||||
{
|
||||
return (float)(Mathf.Atan2(target.y - vertex.y, target.x - vertex.x) * (180 / Mathf.PI));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6dedae9574fd47d291a2f9012a1ec9e1
|
||||
timeCreated: 1748193767
|
||||
166
Assets/WordConnectGameToolkit/Scripts/GUI/UIManager.cs
Normal file
166
Assets/WordConnectGameToolkit/Scripts/GUI/UIManager.cs
Normal file
@ -0,0 +1,166 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using WordsToolkit.Scripts.Gameplay.Managers;
|
||||
using WordsToolkit.Scripts.Popups;
|
||||
using UnityEngine.UI;
|
||||
using VContainer;
|
||||
using WordsToolkit.Scripts.Enums;
|
||||
using WordsToolkit.Scripts.GUI.Buttons;
|
||||
using WordsToolkit.Scripts.Levels;
|
||||
using WordsToolkit.Scripts.Settings;
|
||||
using WordsToolkit.Scripts.System;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI
|
||||
{
|
||||
public class UIManager : MonoBehaviour
|
||||
{
|
||||
[Inject]
|
||||
private MenuManager menuManager;
|
||||
[Inject]
|
||||
private IObjectResolver resolver;
|
||||
[Inject]
|
||||
private GameSettings gameSettings;
|
||||
[Inject]
|
||||
private FieldManager fieldManager;
|
||||
|
||||
public ButtonPopup[] buttonsToOpenPopups;
|
||||
|
||||
[SerializeField] private CustomButton openRandomTileButton;
|
||||
[SerializeField] private CustomButton openSelectedTileButton;
|
||||
[SerializeField] private CustomButton giftButton;
|
||||
[SerializeField] private TimerDisplay timerDisplay;
|
||||
|
||||
private LevelManager levelManager;
|
||||
|
||||
private const string GIFT_BUTTON_SHOWN_KEY = "GiftButtonShown";
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
foreach (var buttonPopup in buttonsToOpenPopups)
|
||||
{
|
||||
resolver.Inject(buttonPopup);
|
||||
buttonPopup.Init();
|
||||
}
|
||||
|
||||
// Initialize gift button visibility
|
||||
if (giftButton != null)
|
||||
{
|
||||
giftButton.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveGiftButtonState(bool shown)
|
||||
{
|
||||
PlayerPrefs.SetInt(GIFT_BUTTON_SHOWN_KEY, shown ? 1 : 0);
|
||||
PlayerPrefs.Save();
|
||||
}
|
||||
|
||||
private bool LoadGiftButtonState()
|
||||
{
|
||||
return PlayerPrefs.GetInt(GIFT_BUTTON_SHOWN_KEY, 0) == 1;
|
||||
}
|
||||
|
||||
private void UpdateGiftButtonVisibility(bool hasSpecialItems)
|
||||
{
|
||||
if (giftButton != null)
|
||||
{
|
||||
bool shouldShow = hasSpecialItems || LoadGiftButtonState();
|
||||
giftButton.gameObject.SetActive(shouldShow);
|
||||
if (shouldShow)
|
||||
{
|
||||
SaveGiftButtonState(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
EventManager.GetEvent<Level>(EGameEvent.LevelLoaded).Subscribe(OnLevelLoaded);
|
||||
EventManager.OnGameStateChanged += HandleGameStateChange;
|
||||
if (fieldManager != null && giftButton != null)
|
||||
{
|
||||
UpdateGiftButtonVisibility(fieldManager.HasSpecialItems());
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
EventManager.GetEvent<Level>(EGameEvent.LevelLoaded).Unsubscribe(OnLevelLoaded);
|
||||
EventManager.OnGameStateChanged -= HandleGameStateChange;
|
||||
}
|
||||
|
||||
private void OnLevelLoaded(Level obj)
|
||||
{
|
||||
foreach (var boost in gameSettings.boostLevels)
|
||||
{
|
||||
if(openRandomTileButton.CompareTag(boost.tag))
|
||||
{
|
||||
openRandomTileButton.gameObject.SetActive(boost.level <= obj.number);
|
||||
}
|
||||
if(openSelectedTileButton.CompareTag(boost.tag))
|
||||
{
|
||||
openSelectedTileButton.gameObject.SetActive(boost.level <= obj.number);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for special items and update gift button visibility
|
||||
if (giftButton != null)
|
||||
{
|
||||
UpdateGiftButtonVisibility(fieldManager.HasSpecialItems());
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleGameStateChange(EGameState newState)
|
||||
{
|
||||
UpdateButtonInteractability(newState);
|
||||
}
|
||||
|
||||
private void UpdateButtonInteractability(EGameState gameState)
|
||||
{
|
||||
if (buttonsToOpenPopups == null) return;
|
||||
|
||||
bool isInteractable = gameState == EGameState.Playing;
|
||||
|
||||
foreach (var buttonPopup in buttonsToOpenPopups)
|
||||
{
|
||||
if (buttonPopup.button != null)
|
||||
{
|
||||
buttonPopup.button.interactable = isInteractable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
[Serializable]
|
||||
public class ButtonPopup
|
||||
{
|
||||
public CustomButton button;
|
||||
public Popup popupRef;
|
||||
public Button.ButtonClickedEvent onClick => button.onClick;
|
||||
[Inject]
|
||||
private MenuManager menuManager;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
button?.onClick.AddListener(() =>
|
||||
{
|
||||
if (popupRef)
|
||||
{
|
||||
this.menuManager.ShowPopup(popupRef);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b46e327667804829b444b6866d5d5e8e
|
||||
timeCreated: 1727667184
|
||||
86
Assets/WordConnectGameToolkit/Scripts/GUI/WordBubble.cs
Normal file
86
Assets/WordConnectGameToolkit/Scripts/GUI/WordBubble.cs
Normal file
@ -0,0 +1,86 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using DG.Tweening;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace WordsToolkit.Scripts.GUI
|
||||
{
|
||||
public class WordBubble : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private TextMeshProUGUI wordText;
|
||||
public float shakeDuration = 0.5f;
|
||||
public float shakeMagnitude = 0.1f;
|
||||
public int vibratoCount = 10;
|
||||
public float randomness = 90f;
|
||||
public float destroyDelay = 0.2f;
|
||||
|
||||
private RectTransform _rectTransform;
|
||||
private ContentSizeFitter _contentSizeFitter;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_rectTransform = GetComponent<RectTransform>();
|
||||
_contentSizeFitter = GetComponent<ContentSizeFitter>();
|
||||
}
|
||||
|
||||
public void SetWord(string word)
|
||||
{
|
||||
wordText.text = word;
|
||||
|
||||
// Force content size fitter and layout update
|
||||
if (_contentSizeFitter != null)
|
||||
{
|
||||
Canvas.ForceUpdateCanvases();
|
||||
_contentSizeFitter.SetLayoutHorizontal();
|
||||
_contentSizeFitter.SetLayoutVertical();
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(_rectTransform);
|
||||
}
|
||||
|
||||
Shake();
|
||||
}
|
||||
|
||||
private void Shake()
|
||||
{
|
||||
if (_rectTransform != null)
|
||||
{
|
||||
// Create sequence for shake and fade out
|
||||
Sequence sequence = DOTween.Sequence();
|
||||
|
||||
// Add shake animation
|
||||
sequence.Append(_rectTransform.DOShakeAnchorPos(
|
||||
duration: shakeDuration,
|
||||
strength: shakeMagnitude * 100f,
|
||||
vibrato: vibratoCount,
|
||||
randomness: randomness,
|
||||
fadeOut: true
|
||||
));
|
||||
|
||||
// Add fade out and destroy
|
||||
sequence.AppendInterval(destroyDelay);
|
||||
sequence.Append(wordText.DOFade(0, 0.2f));
|
||||
sequence.OnComplete(() => {
|
||||
Destroy(gameObject);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
_rectTransform?.DOKill();
|
||||
wordText?.DOKill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 23031a4694394b68b71a3e296c5a4e55
|
||||
timeCreated: 1743012191
|
||||
Reference in New Issue
Block a user