/// <summary> /// Calculate FIRST from concat element and a /// </summary> /// <param name="element"></param> /// <param name="a"></param> /// <returns></returns> private List <TerminalProduction> CalculateFirst(IProductionElement element, TerminalProduction a) { if (element is EpsilonProduction || element is EOFProduction) { return(new List <TerminalProduction>() { a }); } if (element is TerminalProduction) { return(new List <TerminalProduction>() { (TerminalProduction)element }); } var t = (element as NonTerminalProduction).NonTerminal; var rv = new List <TerminalProduction>(); rv.AddRange(t.First); if (t.First.Contains(new EpsilonProduction())) { rv.Add(a); } return(rv); }
public LRNodeElement(GrammarRule rule, TerminalProduction production) { GrammarRule = rule; TerminalProduction = production; }
private void DefineTestBldg() { #region terminals var boxTerm = new TerminalProduction(UnityEngine.GameObject.CreatePrimitive(PrimitiveType.Cube)); var wallTerm = new TerminalProduction(TerminalWall).Move(new Vector3(0, -16, 0)); var archTerm = new TerminalProduction(TerminalArch).Move(new Vector3(0, -16, 0)); // this particukar .obj isn't centered at 0,0,0 so we shift it's coords as needed var plankTerm = new TerminalProduction(WoodPlank).Rotate(Quaternion.AngleAxis(180f, Vector3.right)); #endregion #region outers var bldg = new RegistrarProduction("Bldg", new CubeProductionScope(new Bounds(new Vector3(0, 16, 0), new Vector3(32, 32, 32)), Quaternion.identity)) .Rotate(Quaternion.AngleAxis(0, Vector3.up)) .Scale(new ScaleProduction { IsAbsolute = new[] { false, false, false }, Magnitude = new[] { 1f, 1f, 1f } }); ProductionDictionary.Add(bldg.Name, bldg); var outerWall = new RegistrarProduction("TestWall", bldg.Scope).Terminate(archTerm); var floorRepeatX = new Func <RegistrarProduction, RepeatProduction>(parentProd => new RepeatProduction(parentProd) { Name = "", IsOccluder = false, Magnitude = 5f, RemainderMode = RepeatRemainderMode.MergeFirstAndLast, RepetitionAxis = ProductionAxis.X, ReplicandProduction = parent => new RegistrarProduction("", parent.Scope).Terminate(plankTerm) }); var floorRepeatZ = new Func <RegistrarProduction, RepeatProduction>(parentProd => new RepeatProduction(parentProd) { Name = "", IsOccluder = false, Magnitude = 1.5f, RemainderMode = RepeatRemainderMode.MergeFirstAndLast, RepetitionAxis = ProductionAxis.Z, ReplicandProduction = parent => new RegistrarProduction("", parent.Scope).Repeat(floorRepeatX) }); bldg.Select(new SelectProduction(bldg) { Faces = new[] { ScopeFace.Front, ScopeFace.Back, ScopeFace.Left, ScopeFace.Right }, FaceBreadth = 5f, IsAbsolute = true, Name = "TestWalls", SelectandProduction = outerWall }); //bldg.Select(parentProd => new SelectProduction(parentProd) //{ // Faces = new[] { ScopeFace.Bottom }, // FaceBreadth = 1f, // IsAbsolute = true, // Name = "TestFloor", // SelectandProduction = new RegistrarProduction("", parentProd.Scope).Repeat(floorRepeatZ) //}); #endregion #region inners var wallTest = new Func <RegistrarProduction, SwitchProduction>(parentProd => new SwitchProduction(parentProd) { Cases = new List <CaseProduction> { new CaseProduction { Case = parent => parent.Scope.IsOccluded(), Body = parent => new RegistrarProduction("", parent.Scope).Terminate(wallTerm) }, new CaseProduction { Case = delegate(RegistrarProduction parent) { var occlusionProbe = new RegistrarProduction("occlusionProbe", parent.Scope) { IsOccluder = true }; occlusionProbe.Scale(new ScaleProduction { IsAbsolute = new[] { true, false, true }, Magnitude = new[] { // make the walls a bit thicker--but not as long. parent.Scope.Bounds.size.x + .01f, // .51f //so walls that meet at the corner won't mark each other as occluded; 1f, // only walls with adjacent FACES occlude each other parent.Scope.Bounds.size.z - 1.04f //2.99f // can we generalize/simplify this trick? } }); ModuleProduction.Occluders.Add(occlusionProbe.Scope); return(true); return(!occlusionProbe.Scope.IsOccluded()); }, Body = parent => //RegistrarProduction.Empty new RegistrarProduction("wallOccluder", parent.Scope) { IsOccluder = false } .Scale(new ScaleProduction { IsAbsolute = new[] { true, false, true }, Magnitude = new[] { // make the walls a bit thicker--but not as long. parent.Scope.Bounds.size.x + .01f, // .51f //so walls that meet at the corner won't mark each other as occluded; 1f, // only walls with adjacent FACES occlude each other parent.Scope.Bounds.size.z - 1.02f //2.99f // can we generalize/simplify this trick? } }).Terminate(boxTerm) } }, DefaultProduction = RegistrarProduction.Empty, Name = "wallTest" }); var roomTermCase = new CaseProduction { Case = parent => (UnityEngine.Random.Range(0, 5) > 3.5) || parent.Scope.Bounds.size.x < 8 && parent.Scope.Bounds.size.z < 8, Body = parent => new SelectProduction(parent) { Faces = new[] { ScopeFace.Front, ScopeFace.Left, ScopeFace.Back, ScopeFace.Right }, FaceBreadth = .5f, IsAbsolute = true, SelectandProduction = new RegistrarProduction("", parent.Scope).Switch(wallTest) } }; var roomDivideX = new CaseProduction { Case = parent1 => parent1.Scope.Bounds.size.x >= parent1.Scope.Bounds.size.z, Body = parent1 => new DivideProduction(parent1) { DivisionAxis = ProductionAxis.X, Divisors = new [] { new DivisorProduction { DividendProduction = parent2 => (RegistrarProduction)parent2.Clone(), Magnitude = .5f, IsAbsolute = false }, new DivisorProduction { DividendProduction = parent2 => (RegistrarProduction)parent2.Clone(), Magnitude = .5f, IsAbsolute = false } } } }; var roomDivideZ = new CaseProduction { Case = parent1 => parent1.Scope.Bounds.size.x < parent1.Scope.Bounds.size.z, Body = parent1 => new DivideProduction(parent1) { DivisionAxis = ProductionAxis.Z, Divisors = new[] { new DivisorProduction { DividendProduction = parent2 => (RegistrarProduction)parent2.Clone(), Magnitude = .5f, IsAbsolute = false }, new DivisorProduction { DividendProduction = parent2 => (RegistrarProduction)parent2.Clone(), Magnitude = .5f, IsAbsolute = false } } } }; var firstFloorRooms = new RegistrarProduction("FirstFloorRooms", bldg.Scope) .Scale(new ScaleProduction { Magnitude = new[] { 1f, 0.1f, 1f }, IsAbsolute = new[] { false, false, false } }) .Switch(parentProd => new SwitchProduction(parentProd) { Cases = new List <CaseProduction> { roomTermCase, roomDivideX, roomDivideZ }, DefaultProduction = RegistrarProduction.Empty }); bldg.BoxSplit(firstFloorRooms); #endregion }