mirror of
https://github.com/Ratstail91/Mementos.git
synced 2025-11-29 10:34:27 +11:00
Committed everything
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ink.Parsed
|
||||
{
|
||||
public class Path
|
||||
{
|
||||
public FlowLevel baseTargetLevel {
|
||||
get {
|
||||
if (baseLevelIsAmbiguous)
|
||||
return FlowLevel.Story;
|
||||
else
|
||||
return (FlowLevel) _baseTargetLevel;
|
||||
}
|
||||
}
|
||||
|
||||
public bool baseLevelIsAmbiguous {
|
||||
get {
|
||||
return _baseTargetLevel == null;
|
||||
}
|
||||
}
|
||||
|
||||
public string firstComponent {
|
||||
get {
|
||||
if (components == null || components.Count == 0)
|
||||
return null;
|
||||
|
||||
return components [0].name;
|
||||
}
|
||||
}
|
||||
|
||||
public int numberOfComponents {
|
||||
get {
|
||||
return components.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public string dotSeparatedComponents {
|
||||
get {
|
||||
if( _dotSeparatedComponents == null ) {
|
||||
_dotSeparatedComponents = string.Join(".", components.Select(c => c?.name));
|
||||
}
|
||||
|
||||
return _dotSeparatedComponents;
|
||||
}
|
||||
}
|
||||
string _dotSeparatedComponents;
|
||||
|
||||
public List<Identifier> components { get; }
|
||||
|
||||
public Path(FlowLevel baseFlowLevel, List<Identifier> components)
|
||||
{
|
||||
_baseTargetLevel = baseFlowLevel;
|
||||
this.components = components;
|
||||
}
|
||||
|
||||
public Path(List<Identifier> components)
|
||||
{
|
||||
_baseTargetLevel = null;
|
||||
this.components = components;
|
||||
}
|
||||
|
||||
public Path(Identifier ambiguousName)
|
||||
{
|
||||
_baseTargetLevel = null;
|
||||
components = new List<Identifier> ();
|
||||
components.Add (ambiguousName);
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
if (components == null || components.Count == 0) {
|
||||
if (baseTargetLevel == FlowLevel.WeavePoint)
|
||||
return "-> <next gather point>";
|
||||
else
|
||||
return "<invalid Path>";
|
||||
}
|
||||
|
||||
return "-> " + dotSeparatedComponents;
|
||||
}
|
||||
|
||||
public Parsed.Object ResolveFromContext(Parsed.Object context)
|
||||
{
|
||||
if (components == null || components.Count == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Find base target of path from current context. e.g.
|
||||
// ==> BASE.sub.sub
|
||||
var baseTargetObject = ResolveBaseTarget (context);
|
||||
if (baseTargetObject == null) {
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
// Given base of path, resolve final target by working deeper into hierarchy
|
||||
// e.g. ==> base.mid.FINAL
|
||||
if (components.Count > 1) {
|
||||
return ResolveTailComponents (baseTargetObject);
|
||||
}
|
||||
|
||||
return baseTargetObject;
|
||||
}
|
||||
|
||||
// Find the root object from the base, i.e. root from:
|
||||
// root.sub1.sub2
|
||||
Parsed.Object ResolveBaseTarget(Parsed.Object originalContext)
|
||||
{
|
||||
var firstComp = firstComponent;
|
||||
|
||||
// Work up the ancestry to find the node that has the named object
|
||||
Parsed.Object ancestorContext = originalContext;
|
||||
while (ancestorContext != null) {
|
||||
|
||||
// Only allow deep search when searching deeper from original context.
|
||||
// Don't allow search upward *then* downward, since that's searching *everywhere*!
|
||||
// Allowed examples:
|
||||
// - From an inner gather of a stitch, you should search up to find a knot called 'x'
|
||||
// at the root of a story, but not a stitch called 'x' in that knot.
|
||||
// - However, from within a knot, you should be able to find a gather/choice
|
||||
// anywhere called 'x'
|
||||
// (that latter example is quite loose, but we allow it)
|
||||
bool deepSearch = ancestorContext == originalContext;
|
||||
|
||||
var foundBase = TryGetChildFromContext (ancestorContext, firstComp, null, deepSearch);
|
||||
if (foundBase != null)
|
||||
return foundBase;
|
||||
|
||||
ancestorContext = ancestorContext.parent;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Find the final child from path given root, i.e.:
|
||||
// root.sub.finalChild
|
||||
Parsed.Object ResolveTailComponents(Parsed.Object rootTarget)
|
||||
{
|
||||
Parsed.Object foundComponent = rootTarget;
|
||||
for (int i = 1; i < components.Count; ++i) {
|
||||
var compName = components [i].name;
|
||||
|
||||
FlowLevel minimumExpectedLevel;
|
||||
var foundFlow = foundComponent as FlowBase;
|
||||
if (foundFlow != null)
|
||||
minimumExpectedLevel = (FlowLevel)(foundFlow.flowLevel + 1);
|
||||
else
|
||||
minimumExpectedLevel = FlowLevel.WeavePoint;
|
||||
|
||||
|
||||
foundComponent = TryGetChildFromContext (foundComponent, compName, minimumExpectedLevel);
|
||||
if (foundComponent == null)
|
||||
break;
|
||||
}
|
||||
|
||||
return foundComponent;
|
||||
}
|
||||
|
||||
// See whether "context" contains a child with a given name at a given flow level
|
||||
// Can either be a named knot/stitch (a FlowBase) or a weave point within a Weave (Choice or Gather)
|
||||
// This function also ignores any other object types that are neither FlowBase nor Weave.
|
||||
// Called from both ResolveBase (force deep) and ResolveTail for the individual components.
|
||||
Parsed.Object TryGetChildFromContext(Parsed.Object context, string childName, FlowLevel? minimumLevel, bool forceDeepSearch = false)
|
||||
{
|
||||
// null childLevel means that we don't know where to find it
|
||||
bool ambiguousChildLevel = minimumLevel == null;
|
||||
|
||||
// Search for WeavePoint within Weave
|
||||
var weaveContext = context as Weave;
|
||||
if ( weaveContext != null && (ambiguousChildLevel || minimumLevel == FlowLevel.WeavePoint)) {
|
||||
return (Parsed.Object) weaveContext.WeavePointNamed (childName);
|
||||
}
|
||||
|
||||
// Search for content within Flow (either a sub-Flow or a WeavePoint)
|
||||
var flowContext = context as FlowBase;
|
||||
if (flowContext != null) {
|
||||
|
||||
// When searching within a Knot, allow a deep searches so that
|
||||
// named weave points (choices and gathers) can be found within any stitch
|
||||
// Otherwise, we just search within the immediate object.
|
||||
var shouldDeepSearch = forceDeepSearch || flowContext.flowLevel == FlowLevel.Knot;
|
||||
return flowContext.ContentWithNameAtLevel (childName, minimumLevel, shouldDeepSearch);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
FlowLevel? _baseTargetLevel;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user