void DrawRule <T>(string caption, ref bool ruleEnabled, ref string ruleClassName) where T : ScriptableObject { GUI.enabled = true; EditorGUILayout.BeginHorizontal(); GUILayout.Space(CATEGORY_SPACING); ruleEnabled = EditorGUILayout.ToggleLeft(caption, ruleEnabled); GUI.enabled = ruleEnabled; MonoScript script = null; if (ruleClassName != null) { var rule = instanceCache.GetInstance(ruleClassName) as ScriptableObject; if (rule != null) { script = MonoScript.FromScriptableObject(rule); } } var oldScript = script; script = EditorGUILayout.ObjectField(script, typeof(MonoScript), false) as MonoScript; if (oldScript != script && script != null) { ruleClassName = script.GetClass().FullName; } else if (script == null) { ruleClassName = null; } EditorGUILayout.EndHorizontal(); GUI.enabled = true; }
public virtual void ApplyTheme(List <DungeonPropDataAsset> Themes, DungeonSceneProvider SceneProvider) { var instanceCache = new InstanceCache(); var constraintProcessor = GetComponent <SpatialConstraintProcessor>(); if (constraintProcessor != null) { constraintProcessor.Initialize(model, propSockets); } PropBySocketTypeByTheme_t PropBySocketTypeByTheme = new PropBySocketTypeByTheme_t(); foreach (DungeonPropDataAsset Theme in Themes) { CreatePropLookup(Theme, PropBySocketTypeByTheme); } // Collect all the theme override volumes and prepare their theme lookup var overrideVolumes = new List <ThemeOverrideVolume>(); Dictionary <Graph, DungeonPropDataAsset> GraphToThemeMapping = new Dictionary <Graph, DungeonPropDataAsset>(); var dungeon = GetComponent <Dungeon>(); // Process the theme override volumes var themeOverrides = GameObject.FindObjectsOfType <ThemeOverrideVolume>(); foreach (var themeOverride in themeOverrides) { if (themeOverride.dungeon != dungeon) { continue; } overrideVolumes.Add(themeOverride); var graph = themeOverride.overrideTheme; if (graph != null && !GraphToThemeMapping.ContainsKey(graph)) { DungeonPropDataAsset theme = new DungeonPropDataAsset(); theme.BuildFromGraph(themeOverride.overrideTheme); GraphToThemeMapping.Add(themeOverride.overrideTheme, theme); CreatePropLookup(theme, PropBySocketTypeByTheme); } } var srandom = new PMRandom(config.Seed); // Fill up the prop sockets with the defined mesh data for (int i = 0; i < PropSockets.Count; i++) { PropSocket socket = PropSockets[i]; DungeonPropDataAsset ThemeToUse = GetBestMatchedTheme(Themes, socket, PropBySocketTypeByTheme); // PropAsset; // Check if this socket resides within a override volume { var socketPosition = Matrix.GetTranslation(ref socket.Transform); foreach (var volume in overrideVolumes) { if (volume.GetBounds().Contains(socketPosition)) { var graph = volume.overrideTheme; if (graph != null && GraphToThemeMapping.ContainsKey(graph)) { ThemeToUse = GraphToThemeMapping[volume.overrideTheme]; break; } } } } if (ThemeToUse == null) { continue; } PropBySocketType_t PropBySocketType = PropBySocketTypeByTheme[ThemeToUse]; if (PropBySocketType.ContainsKey(socket.SocketType)) { List <PropTypeData> props = PropBySocketType[socket.SocketType]; foreach (PropTypeData prop in props) { bool insertMesh = false; Matrix4x4 transform = socket.Transform * prop.Offset; if (prop.UseSelectionRule && prop.SelectorRuleClassName != null) { var selectorRule = instanceCache.GetInstance(prop.SelectorRuleClassName) as SelectorRule; if (selectorRule != null) { // Run the selection rule logic to determine if we need to insert this mesh in the scene insertMesh = selectorRule.CanSelect(socket, transform, model, random.UniformRandom); } } else { // Perform probability based selection logic float probability = srandom.GetNextUniformFloat(); insertMesh = (probability < prop.Affinity); } if (insertMesh && prop.useSpatialConstraint && prop.spatialConstraint != null) { Matrix4x4 spatialOffset; if (!ProcessSpatialConstraint(constraintProcessor, prop.spatialConstraint, socket, out spatialOffset)) { // Fails spatial constraint insertMesh = false; } else { // Apply the offset var markerOffset = socket.Transform; if (prop.spatialConstraint != null && !prop.spatialConstraint.applyMarkerRotation) { var markerPosition = Matrix.GetTranslation(ref markerOffset); var markerScale = Matrix.GetScale(ref markerOffset); markerOffset = Matrix4x4.TRS(markerPosition, Quaternion.identity, markerScale); } transform = markerOffset * spatialOffset * prop.Offset; } } if (insertMesh) { // Attach this prop to the socket // Apply transformation logic, if specified if (prop.UseTransformRule && prop.TransformRuleClassName != null && prop.TransformRuleClassName.Length > 0) { var transformer = instanceCache.GetInstance(prop.TransformRuleClassName) as TransformationRule; if (transformer != null) { Vector3 _position, _scale; Quaternion _rotation; transformer.GetTransform(socket, model, transform, random.UniformRandom, out _position, out _rotation, out _scale); var offset = Matrix4x4.TRS(_position, _rotation, _scale); transform = transform * offset; } } if (prop is GameObjectPropTypeData) { var gameObjectProp = prop as GameObjectPropTypeData; SceneProvider.AddGameObject(gameObjectProp, transform); } else if (prop is GameObjectArrayPropTypeData) { var gameObjectArrayProp = prop as GameObjectArrayPropTypeData; int count = gameObjectArrayProp.Templates.Length; int index = Mathf.FloorToInt(random.GetNextUniformFloat() * count) % count; SceneProvider.AddGameObjectFromArray(gameObjectArrayProp, index, transform); } else if (prop is SpritePropTypeData) { var spriteProp = prop as SpritePropTypeData; SceneProvider.AddSprite(spriteProp, transform); } // TODO: Handle light creation // Add child sockets if any foreach (PropChildSocketData ChildSocket in prop.ChildSockets) { Matrix4x4 childTransform = transform * ChildSocket.Offset; EmitMarker(ChildSocket.SocketType, childTransform, socket.gridPosition, socket.cellId); } if (prop.ConsumeOnAttach) { // Attach no more on this socket break; } } } } } if (constraintProcessor != null) { constraintProcessor.Cleanup(); } }