279 lines
11 KiB
C#
279 lines
11 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Sirenix.OdinInspector;
|
|
using UnityEngine;
|
|
using UnityEngine.Serialization;
|
|
|
|
namespace Ichni.Story.UI
|
|
{
|
|
public partial class Storyline : MonoBehaviour
|
|
{
|
|
[Header("UI References")]
|
|
public RectTransform content; // Content of ScrollRect
|
|
[FormerlySerializedAs("textBlockPrefab")] public GameObject dialogBlockPrefab; // Prefab of UI Node
|
|
public GameObject musicBlockPrefab;
|
|
public GameObject tutorialBlockPrefab;
|
|
public GameObject connectionCurvePrefab; // Prefab of connection curve
|
|
|
|
[Header("Layout Settings")]
|
|
public float marginLeft = 50f; // additive space on the left
|
|
public float marginRight = 50f; // Extra space on the right
|
|
public float marginTop = 50f; // Extra space on the top
|
|
public float marginBottom = 50f; // Extra space on the bottom
|
|
public RectTransform connectionContainer;
|
|
|
|
public StoryBlockUIBase currentBlock;
|
|
|
|
public List<StoryBlockUIBase> storyBlocks;
|
|
public List<DialogBlockUI> dialogBlocks;
|
|
public List<SongBlockUI> songBlocks;
|
|
public List<TutorialBlockUI> tutorialBlocks;
|
|
public List<BlockConnectorUI> connectors;
|
|
|
|
private void Start()
|
|
{
|
|
storyBlocks = new List<StoryBlockUIBase>();
|
|
dialogBlocks = new List<DialogBlockUI>();
|
|
songBlocks = new List<SongBlockUI>();
|
|
tutorialBlocks = new List<TutorialBlockUI>();
|
|
connectors = new List<BlockConnectorUI>();
|
|
|
|
//TutorialBlockUI t0 = GenerateTutorialBlock(new Vector2(200, -400), "ZakoCurse 0");
|
|
//TextBlockUI b1 = GenerateTextBlock("Departure_P1_A", new Vector2(1000, -400), StoryBlockState.Current);
|
|
|
|
SetUpStoryline(ChapterSelectionManager.instance.currentChapter);
|
|
|
|
/*GenerateTextBlock("Departure_P1_A", new Vector2(1000, -400), StoryBlockState.Current);
|
|
GenerateTextBlock("Departure_P2_A", new Vector2(1500, -400), StoryBlockState.Current);
|
|
GenerateConnector("Departure_P1_A", "Departure_P2_A");*/
|
|
|
|
SetUpBackground();
|
|
connectionContainer.SetParent(content);
|
|
connectionContainer.SetAsFirstSibling();
|
|
}
|
|
}
|
|
|
|
public partial class Storyline
|
|
{
|
|
public TutorialBlockUI GenerateTutorialBlock(string blockName, Vector2 position, StoryBlockState state)
|
|
{
|
|
TutorialBlockUI block = Instantiate(tutorialBlockPrefab, content).GetComponent<TutorialBlockUI>();
|
|
StoryData storyData = StoryManager.instance.storyDatas[ChapterSelectionManager.instance.currentChapter];
|
|
TutorialBlockData blockData = storyData.tutorialBlockDatas.FirstOrDefault(data => data.blockName == blockName);
|
|
|
|
if (blockData == null) throw new KeyNotFoundException("There is no block with name " + blockName);
|
|
|
|
block.Initialize(blockData.blockName, position, new Vector2(marginLeft, 0), blockData.blockSize, state, blockData.tutorialName);
|
|
|
|
storyBlocks.Add(block);
|
|
tutorialBlocks.Add(block);
|
|
|
|
return block;
|
|
}
|
|
|
|
public DialogBlockUI GenerateDialogBlock(string blockName, Vector2 position, StoryBlockState state)
|
|
{
|
|
DialogBlockUI block = Instantiate(dialogBlockPrefab, content).GetComponent<DialogBlockUI>();
|
|
StoryData storyData = StoryManager.instance.storyDatas[ChapterSelectionManager.instance.currentChapter];
|
|
DialogBlockData blockData = storyData.dialogBlockDatas.FirstOrDefault(data => data.blockName == blockName);
|
|
|
|
if (blockData == null) throw new KeyNotFoundException("There is no block with name " + blockName);
|
|
|
|
block.Initialize(blockData.blockName, position, new Vector2(marginLeft, 0), blockData.blockSize, state, blockData.dialogTitle);
|
|
|
|
storyBlocks.Add(block);
|
|
dialogBlocks.Add(block);
|
|
|
|
return block;
|
|
}
|
|
|
|
public SongBlockUI GenerateSongBlock(string blockName, Vector2 position, StoryBlockState state)
|
|
{
|
|
SongBlockUI block = Instantiate(musicBlockPrefab, content).GetComponent<SongBlockUI>();
|
|
StoryData storyData = StoryManager.instance.storyDatas[ChapterSelectionManager.instance.currentChapter];
|
|
SongBlockData blockData = storyData.songBlockDatas.FirstOrDefault(data => data.blockName == blockName);
|
|
|
|
if (blockData == null) throw new KeyNotFoundException("There is no block with name " + blockName);
|
|
|
|
block.Initialize(blockName,position,new Vector2(marginLeft, 0), blockData.blockSize, state, blockData.songName);
|
|
|
|
storyBlocks.Add(block);
|
|
songBlocks.Add(block);
|
|
|
|
return block;
|
|
}
|
|
|
|
public void GenerateConnector(StoryBlockUIBase startBlock, StoryBlockUIBase endBlock)
|
|
{
|
|
BlockConnectorUI connector = Instantiate(connectionCurvePrefab, connectionContainer).GetComponent<BlockConnectorUI>();
|
|
|
|
Vector2 startPosition = SpaceConverter.GetLocalUIPosition(startBlock.outPort, GetComponent<RectTransform>());
|
|
Vector2 endPosition = SpaceConverter.GetLocalUIPosition(endBlock.inPort, GetComponent<RectTransform>());
|
|
|
|
connector.startBlock = startBlock;
|
|
connector.endBlock = endBlock;
|
|
|
|
connector.SetCurve(startPosition, endPosition);
|
|
connectors.Add(connector);
|
|
}
|
|
|
|
public void GenerateConnector(string startBlockName, string endBlockName)
|
|
{
|
|
StoryBlockUIBase startBlock = storyBlocks.FirstOrDefault(block => block.blockName == startBlockName);
|
|
StoryBlockUIBase endBlock = storyBlocks.FirstOrDefault(block => block.blockName == endBlockName);
|
|
GenerateConnector(startBlock, endBlock);
|
|
}
|
|
}
|
|
|
|
public partial class Storyline
|
|
{
|
|
private void ClearStoryline()
|
|
{
|
|
foreach (var block in storyBlocks)
|
|
{
|
|
Destroy(block.gameObject);
|
|
}
|
|
storyBlocks.Clear();
|
|
dialogBlocks.Clear();
|
|
songBlocks.Clear();
|
|
tutorialBlocks.Clear();
|
|
|
|
foreach (var connector in connectors)
|
|
{
|
|
Destroy(connector.gameObject);
|
|
}
|
|
connectors.Clear();
|
|
|
|
content.sizeDelta = Vector2.zero;
|
|
}
|
|
|
|
private void SetUpBackground()
|
|
{
|
|
float maxRight = float.MinValue;
|
|
|
|
foreach (var block in storyBlocks)
|
|
{
|
|
float rightEdge = block.blockRect.anchoredPosition.x + block.blockRect.sizeDelta.x * 0.5f;
|
|
if (rightEdge > maxRight)
|
|
{
|
|
maxRight = rightEdge;
|
|
}
|
|
}
|
|
|
|
maxRight += marginRight;
|
|
|
|
if (maxRight < 2560f)
|
|
{
|
|
maxRight = 2560f;
|
|
}
|
|
|
|
|
|
float lowY = float.MaxValue;
|
|
|
|
foreach (var block in storyBlocks)
|
|
{
|
|
float bottomEdge = block.blockRect.anchoredPosition.y - block.blockRect.sizeDelta.y * 0.5f;
|
|
if (bottomEdge < lowY)
|
|
{
|
|
lowY = bottomEdge;
|
|
}
|
|
}
|
|
|
|
float maxHeight = Mathf.Abs(lowY) + marginTop + marginBottom;
|
|
|
|
if (maxHeight < 1440f)
|
|
{
|
|
maxHeight = 1440f;
|
|
}
|
|
|
|
content.sizeDelta = new Vector2(maxRight, maxHeight);
|
|
}
|
|
}
|
|
|
|
public partial class Storyline
|
|
{
|
|
public void SetUpStoryline(string chapterName)
|
|
{
|
|
GameSaveManager.instance.StorySaveModule.LoadStoryline(chapterName);
|
|
|
|
foreach (var blockSave in GameSaveManager.instance.StorySaveModule.tutorialBlockSaves[chapterName])
|
|
{
|
|
GenerateTutorialBlock(blockSave.blockName, blockSave.position, blockSave.state);
|
|
}
|
|
|
|
foreach (var blockSave in GameSaveManager.instance.StorySaveModule.songBlockSaves[chapterName])
|
|
{
|
|
GenerateSongBlock(blockSave.blockName, blockSave.position, blockSave.state);
|
|
}
|
|
|
|
foreach (var blockSave in GameSaveManager.instance.StorySaveModule.dialogBlockSaves[chapterName])
|
|
{
|
|
GenerateDialogBlock(blockSave.blockName, blockSave.position, blockSave.state);
|
|
}
|
|
|
|
foreach (var connectorSave in GameSaveManager.instance.StorySaveModule.connectorSaves[chapterName])
|
|
{
|
|
GenerateConnector(connectorSave.startBlockName, connectorSave.endBlockName);
|
|
}
|
|
}
|
|
|
|
[Button]
|
|
public void SaveStoryline(string chapterName)
|
|
{
|
|
List<TutorialBlockSave> tutorialBlockSaves =
|
|
tutorialBlocks.Select(block => block.GetBlockSave() as TutorialBlockSave).ToList();
|
|
|
|
List<SongBlockSave> songBlockSaves =
|
|
songBlocks.Select(block => block.GetBlockSave() as SongBlockSave).ToList();
|
|
|
|
List<DialogBlockSave> dialogBlockSaves =
|
|
dialogBlocks.Select(block => block.GetBlockSave() as DialogBlockSave).ToList();
|
|
|
|
List<BlockConnectorSave> connectorSaves =
|
|
connectors.Select(connector => new BlockConnectorSave(connector.startBlock.blockName, connector.endBlock.blockName)).ToList();
|
|
|
|
GameSaveManager.instance.StorySaveModule.SaveStoryline(
|
|
chapterName, tutorialBlockSaves, songBlockSaves, dialogBlockSaves, connectorSaves);
|
|
}
|
|
|
|
[Button]
|
|
public void ResetStory()
|
|
{
|
|
ClearStoryline();
|
|
|
|
StoryData storyData = StoryManager.instance.storyDatas[ChapterSelectionManager.instance.currentChapter];
|
|
List<InitialBlockData> initialBlocks = storyData.initialBlocks;
|
|
|
|
foreach (InitialBlockData blockData in initialBlocks)
|
|
{
|
|
storyData.GetDataByName(blockData.blockName, out Type dataType);
|
|
|
|
if (dataType == typeof(TutorialBlockData))
|
|
{
|
|
GenerateTutorialBlock(blockData.blockName, blockData.blockPosition, blockData.initialState);
|
|
}
|
|
else if (dataType == typeof(DialogBlockData))
|
|
{
|
|
GenerateDialogBlock(blockData.blockName, blockData.blockPosition, blockData.initialState);
|
|
}
|
|
else if (dataType == typeof(SongBlockData))
|
|
{
|
|
GenerateSongBlock(blockData.blockName, blockData.blockPosition, blockData.initialState);
|
|
}
|
|
}
|
|
|
|
foreach (InitialBlockData blockData in initialBlocks)
|
|
{
|
|
foreach (string nextBlockName in blockData.nextBlocks)
|
|
{
|
|
GenerateConnector(blockData.blockName, nextBlockName);
|
|
}
|
|
}
|
|
|
|
SetUpBackground();
|
|
SaveStoryline(ChapterSelectionManager.instance.currentChapter);
|
|
}
|
|
}
|
|
} |