다이얼로그 작업중

This commit is contained in:
skrwns304@gmail.com
2026-06-09 15:51:29 +09:00
parent 54c6ddee0a
commit 404921f815
172 changed files with 9854 additions and 26 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 32a9038ef099d5a4d87f583d4b99d0b4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,91 @@
using System.Linq;
using Unity.GraphToolkit.Editor;
using UnityEditor.AssetImporters;
using UnityEngine;
namespace Unity.GraphToolkit.Samples.TextureMaker.Editor
{
/// <summary>
/// TextureMakerImporter is a <see cref="ScriptedImporter"/> responsible for creating the texture and adding the
/// texture to the asset, so the graph can be used directly as a texture in the scene.
/// It contains all the Texture logic of the tool.
/// </summary>
[ScriptedImporter(1, TextureMakerGraph.AssetExtension)]
internal class TextureMakerImporter : ScriptedImporter
{
/// <summary>
/// The name of the texture identifier in the asset.
/// </summary>
private const string OutputTextureAssetIdName = "OutputTexture";
/// <summary>
/// Gets or sets the output Texture2D.
/// </summary>
private Texture2D OutputTexture { get; set; }
/// <summary>
/// Called when the asset is imported. This method processes the graph object and creates the texture.
/// </summary>
/// <param name="ctx">The asset import context.</param>
public override void OnImportAsset(AssetImportContext ctx)
{
// The loaded graph may be null if the `Graph.LoadForImporter` method fails to load the asset from the
// specified `ctx.assetPath`.
// This can occur under the following circumstances:
// - The asset path is incorrect, or the asset does not exist at the specified location.
// - The asset located at the specified path is not of type `TextureMakerGraph`.
// - The asset file itself is problematic, such as being corrupted or stored in an unsupported format.
//
// Best practice when dealing with serialization is to account for potential deserialization issues
// by thoroughly validating and safeguarding against impaired or incomplete data.
var graph = GraphDatabase.LoadGraphForImporter<TextureMakerGraph>(ctx.assetPath);
if (graph == null)
{
Debug.LogError($"Failed to load texture maker graph object: {ctx.assetPath}");
return;
}
CompileGraph(graph);
// Adding the texture to the graph object and setting it to be the main asset.
// This allows the generated texture to be used directly in the project and referenced in a material or a scene.
if (OutputTexture != null)
{
ctx.AddObjectToAsset(OutputTextureAssetIdName, OutputTexture);
ctx.SetMainObject(OutputTexture);
}
}
/// <summary>
/// Compiles the provided texture maker graph and updates the output texture based on its evaluated nodes.
/// </summary>
/// <param name="graph">The texture maker graph to compile.</param>
private void CompileGraph(TextureMakerGraph graph)
{
// Get the first CreateTexture Node
// (Only using the first one is a tool design simplification we made for this sample)
var createTextureNode = graph.GetNodes().OfType<CreateTextureNode>().FirstOrDefault();
if (createTextureNode == null)
{
// No need to log an error here, as an error is already logged in the console (see the `OnGraphChanged` method
// overriden in the TextureMakerGraph class).
return;
}
// Initialize the output texture to a default texture
// This enables the graph object to use a default texture when a valid texture evaluator node is not yet available.
OutputTexture = new Texture2D(CreateTextureNode.OutputWidth, CreateTextureNode.OutputHeight);
OutputTexture.name = OutputTextureAssetIdName;
// Get the input port of the CreateTextureNode
var inputPort = createTextureNode.GetInputPortByName(CreateTextureNode.TextureInputName);
// Resolve the texture from the input port
var texture = TextureMakerGraph.ResolvePortValue<Texture2D>(inputPort);
if (texture != null)
{
OutputTexture = new Texture2D(texture.width, texture.height);
OutputTexture.SetPixels(texture.GetPixels());
} // else can happen when the input port is not connected and no embedded value is set
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e14cbdfe3bad40dc9e5cf791df184d43
timeCreated: 1740674216

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 51ff29566e157cc42a82d110da3fa57f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2145001d8b7b79d4d90138544650514d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,38 @@
using System;
using JetBrains.Annotations;
using Unity.GraphToolkit.Editor;
using UnityEngine;
namespace Unity.GraphToolkit.Samples.TextureMaker.Editor
{
/// <summary>
/// Represents the result node in a Texture Maker Graph.
/// </summary>
/// <remarks>
/// The result node serves as the end node in the texture graph, where the final texture is evaluated.
/// </remarks>
[Serializable]
[UsedImplicitly]
internal class CreateTextureNode : Node
{
/// Using constants for port ids provides type safety and ensures consistent references across the implementation
internal const string TextureInputName = "InTexture";
/// <summary>
/// The width of the output texture.
/// </summary>
public const int OutputWidth = 16;
/// <summary>
/// The height of the output texture.
/// </summary>
public const int OutputHeight = 16;
/// <summary>
/// Defines the input for the node.
/// </summary>
protected override void OnDefinePorts(IPortDefinitionContext context)
{
context.AddInputPort<Texture2D>(TextureInputName).Build();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5bbd857d07214e2b97256039bbd713f7
timeCreated: 1740675943

View File

@@ -0,0 +1,22 @@
using Unity.GraphToolkit.Editor;
using UnityEngine;
namespace Unity.GraphToolkit.Samples.TextureMaker.Editor
{
/// <summary>
/// Defines an interface for evaluating Texture ports.
/// </summary>
/// <remarks>
/// This interface is defined by nodes with the ability to output a Texture2D.
/// Implementations of this interface should provide the logic to evaluate a given port model and return the resulting Texture.
/// </remarks>
internal interface ITextureEvaluatorNode
{
/// <summary>
/// Evaluates the specified port and returns the resulting Texture.
/// </summary>
/// <param name="port">The port to evaluate.</param>
/// <returns>The result of the evaluation.</returns>
public Texture2D EvaluateTexturePort(IPort port);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 184980cc4753403d96db0011e12a78b2
timeCreated: 1742204057

View File

@@ -0,0 +1,75 @@
using System;
using JetBrains.Annotations;
using Unity.GraphToolkit.Editor;
using UnityEngine;
namespace Unity.GraphToolkit.Samples.TextureMaker.Editor
{
/// <summary>
/// Represents a node that combines two input textures and produces an output texture where pixel values are the mean
/// of the two input values at the same position.
/// </summary>
[Serializable]
[UsedImplicitly]
internal class MeanColorNode : Node, ITextureEvaluatorNode
{
/// Using constants for port ids provides type safety and ensures consistent references across the implementation
internal const string Texture1InputName = "InTexture1";
internal const string Texture2InputName = "InTexture2";
internal const string TextureOutputName = "OutTexture";
/// <summary>
/// Defines the input and output port for the Mean node.
/// This node takes two textures as input and outputs a Texture2D.
/// </summary>
protected override void OnDefinePorts(IPortDefinitionContext context)
{
context.AddInputPort<Texture2D>(Texture1InputName).Build();
context.AddInputPort<Texture2D>(Texture2InputName).Build();
context.AddOutputPort<Texture2D>(TextureOutputName).Build();
}
/// <summary>
/// Evaluates the specified port and returns the result.
/// </summary>
/// <param name="port">The port model to evaluate.</param>
/// <returns>The result of the evaluation.</returns>
public Texture2D EvaluateTexturePort(IPort port)
{
// Only the output port can be evaluated for this node.
if (port != GetOutputPortByName(TextureOutputName))
return null;
// Get the textures from the ports or the embedded value
Texture2D firstTexture = TextureMakerGraph.ResolvePortValue<Texture2D>(GetInputPortByName(Texture1InputName));
Texture2D secondTexture = TextureMakerGraph.ResolvePortValue<Texture2D>(GetInputPortByName(Texture2InputName));
if (firstTexture != null && secondTexture != null)
{
// Using min dimensions to prevent out-of-bounds access; simplified for learning (production code would handle varying texture sizes)
int width = Math.Min(firstTexture.width, secondTexture.width);
int height = Math.Min(firstTexture.height, secondTexture.height);
Texture2D resultTexture = new Texture2D(width, height);
for (var j = 0; j < height; j++)
{
for (var i = 0; i < width; i++)
{
// Set the color of each pixel in the texture
Color firstColor = firstTexture.GetPixel(i, j);
Color secondColor = secondTexture.GetPixel(i, j);
Color color = (firstColor + secondColor) / 2;
resultTexture.SetPixel(i, j, color);
}
}
return resultTexture;
}
// If one of the input ports have no resolved value, return a default texture
return new Texture2D(CreateTextureNode.OutputWidth, CreateTextureNode.OutputHeight);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2866fff3cefe46638f8fe6860cb86b5e
timeCreated: 1742380071

View File

@@ -0,0 +1,57 @@
using System;
using JetBrains.Annotations;
using Unity.GraphToolkit.Editor;
using UnityEngine;
namespace Unity.GraphToolkit.Samples.TextureMaker.Editor
{
/// <summary>
/// Represents a node that generates a uniform texture from a specified color.
/// </summary>
[Serializable]
[UsedImplicitly]
internal class UniformNode : Node, ITextureEvaluatorNode
{
/// Using constants for port ids provides type safety and ensures consistent references across the implementation
internal const string ColorInputName = "InColor";
internal const string TextureOutputName = "OutTexture";
/// <summary>
/// Defines the input and output port for the Uniform node.
/// This nodes takes a color as input and outputs a Texture2D.
/// </summary>
protected override void OnDefinePorts(IPortDefinitionContext context)
{
context.AddInputPort<Color>(ColorInputName).Build();
context.AddOutputPort<Texture2D>(TextureOutputName).Build();
}
/// <summary>
/// Evaluates the specified port and returns the result.
/// </summary>
/// <param name="port">The port model to evaluate.</param>
/// <returns>The result of the evaluation.</returns>
public Texture2D EvaluateTexturePort(IPort port)
{
// Only the Texture output port can be evaluated for this node.
if (port != GetOutputPortByName(TextureOutputName))
return null;
// Gets the color port.
var colorPort = GetInputPortByName(ColorInputName);
// Get the color from the connected port or the embedded value
var color = TextureMakerGraph.ResolvePortValue<Color>(colorPort);
var texture = new Texture2D(CreateTextureNode.OutputWidth, CreateTextureNode.OutputHeight);
// Set the color of each pixel in the texture
for (var j = 0; j < CreateTextureNode.OutputHeight; j++)
{
for (var i = 0; i < CreateTextureNode.OutputWidth; i++)
{
texture.SetPixel(i, j, color);
}
}
return texture;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5b8ad780581240939565c81dd3d40ce5
timeCreated: 1740675943

View File

@@ -0,0 +1,120 @@
using System;
using System.Linq;
using Unity.GraphToolkit.Editor;
using UnityEditor;
using UnityEngine;
namespace Unity.GraphToolkit.Samples.TextureMaker.Editor
{
/// <summary>
/// Represents the Texture Maker graph.
/// </summary>
/// <remarks> This is the entry point for the Texture Maker tool, it represents a Texture Maker graph.
/// This class extends the Graph Toolkit <see cref="Graph"/> class, which provides a range of default behaviors,
/// reducing the amount of code required to quickly implement a basic graph tool.
/// It also provides customization by allowing you to override specific methods and can be decorated by attributes to
/// tailor the tool's functionality.
/// For example, in this class, we override the OnGraphChanged method to add our custom handling for graph errors and warnings.
/// We also decorated it with the <see cref="GraphAttribute"/>, which specifies the asset extension.
/// </remarks>
[Graph(AssetExtension)]
[Serializable]
internal class TextureMakerGraph : Graph
{
/// <summary>
/// The file extension for Texture Maker graph assets.
/// </summary>
/// <remarks> In Unity, the extension is used to select the right importer, so it must be unique.</remarks>
internal const string AssetExtension = "texmkr";
/// <summary>
/// Create a texture maker asset file.
/// </summary>
[MenuItem("Assets/Create/Graph Toolkit Samples/Texture Maker Graph", false)]
static void CreateAssetFile()
{
GraphDatabase.PromptInProjectBrowserToCreateNewAsset<TextureMakerGraph>();
}
/// <summary>
/// Checks the graph for errors and warnings and adds them to the result object.
/// </summary>
/// <param name="infos">Object implementing <see cref="GraphLogger"/> interface and containing
/// collected errors and warnings</param>
/// <remarks>Errors and warnings are reported by adding them to the GraphLogger object,
/// which is the default reporting mechanism for a Graph Toolkit tool. </remarks>
private void CheckGraphErrors(GraphLogger infos)
{
// Get all CreateTextureNode instances in the graph
var createTextureNodes = GetNodes().OfType<CreateTextureNode>().ToList();
switch (createTextureNodes.Count)
{
case 0:
// This is a tool design choice to log an error if no CreateTextureNode is found in the graph.
// This will result in an error message being logged in the console.
infos.LogError("Add a CreateTextureNode in your Texture graph.");
break;
case > 1:
{
foreach (var createTextureNode in createTextureNodes.Skip(1))
{
// This will result in a warning message being logged in the console and a warning marker being displayed on the node
infos.LogWarning($"TextureMaker only supports one {nameof(CreateTextureNode)} by graph. " +
"Only the first created one will be used.", createTextureNode);
}
break;
}
}
}
/// <summary>
/// Called when the graph changes.
/// </summary>
/// <param name="infos">The GraphLogger object to which errors and warnings are added.</param>
/// <remarks>
/// This method is triggered whenever the graph is modified. It calls `CheckGraphErrors` to validate the graph
/// and report any issues.
/// </remarks>
public override void OnGraphChanged(GraphLogger infos)
{
CheckGraphErrors(infos);
}
/// <summary>
/// Resolves the value from the given port by determining the type of node connected.
/// For constant, variable, and texture evaluator nodes, it extracts the corresponding value.
/// If no connected source is available, it attempts to resolve an embedded value from the port.
/// </summary>
/// <typeparam name="T">The expected type of the port value.</typeparam>
/// <param name="port">The port from which to resolve the value.</param>
/// <returns>
/// The resolved value of type <typeparamref name="T"/> if successful; otherwise, the default value of <typeparamref name="T"/>.
/// </returns>
public static T ResolvePortValue<T>(IPort port)
{
// Get the source port providing input to "port" (null if no connection exists)
var sourcePort = port.firstConnectedPort;
switch (sourcePort?.GetNode())
{
case IConstantNode node:
node.TryGetValue(out T constantValue);
return constantValue;
case IVariableNode node:
node.variable.TryGetDefaultValue(out T variableValue);
return variableValue;
case ITextureEvaluatorNode textureEvaluatorNode:
if (typeof(T).IsAssignableFrom(typeof(Texture2D)))
{
return (T)(object)textureEvaluatorNode.EvaluateTexturePort(sourcePort);
}
break;
case null:
// If no connection exists, try to get "port" 's embedded value (returns type default if unavailable)
port.TryGetValue(out T embeddedValue);
return embeddedValue;
}
return default;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ed470a2448996694b915fbb1456339f6
timeCreated: 1647523327