Files
ichni_Official/Assets/Scripts/Story/StoryUI/Storyline.cs
SoulliesOfficial b19469976a Menu基本完成
2025-06-14 14:42:49 -04:00

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);
}
}
}