private static void ApplySkinModifications(GameObject modelObject, AppliedModifications modifications) { var characterModel = modelObject.GetComponent <CharacterModel>(); LastModelObject = modelObject; ////////////////////////////////////////////////////////////////////////////////////// /// foreach (var mod in ModificationList) { ApplyModification(modelObject, characterModel, mod, modifications); } /// ////////////////////////////////////////////////////////////////////////////////////// }
private static void ApplySkinModifications(GameObject modelObject, AppliedModifications modifications) { var characterModel = modelObject.GetComponent <CharacterModel>(); LastModelObject = modelObject; ////////////////////////////////////////////////////////////////////////////////////// /// TODO: create a loop that iterates through the list of modifications and applies them foreach (var mod in ModificationList) { ApplyModification(modelObject, characterModel, mod, modifications); } /// ////////////////////////////////////////////////////////////////////////////////////// }
private static void ClearSkinModifications(GameObject modelObject, AppliedModifications modifications) { //NOTE: modifications that modify the base bone list need to have their bones removed first before destruction //Modifications that modify the base bone list have to be removed in reverse order in order to maintain correct indexing //Clear Mods that modify base bone list, these need to be done in reverse order while (modifications.BaseModelModifications.Count != 0) { var mod = modifications.BaseModelModifications.Pop(); clearModification(mod, modelObject, modifications); } //clear rest of mods while (modifications.OtherModifications.Count != 0) { clearModification(modifications.OtherModifications[0], modelObject, modifications); //clearmodification calls remove on applied Mod. } //remove the object from modified once all mods are cleared ModifiedObjects.Remove(modelObject); }
//////////////////////////////////////////////////////////////////////////// ////// Local Functions (these should not need to be changed when added to different skins) //private static void SkinDefApply(On.RoR2.SkinDef.orig_Apply orig, SkinDef self, GameObject modelObject) //Old SkinDefApply for use w/ mmhook private static void SkinDefApply(Action <SkinDef, GameObject> orig, SkinDef self, GameObject modelObject) { orig(self, modelObject); RemoveInvalidModelObjects(); ModifiedObjects.TryGetValue(modelObject, out var modificatons); try { //if we are on another character/skin if (self != SkinDef) { if (modificatons != null) { ClearSkinModifications(LastModelObject, modificatons); } return; } if (modificatons == null) { //otherwise if are now applying modded skin and no modifcations have been made, then apply modifications //create new Applied Entry and pass into Apply AppliedModifications NewMods = new AppliedModifications(); ModifiedObjects.Add(modelObject, NewMods); ApplySkinModifications(modelObject, NewMods); } } catch (Exception e) { //error logging may need to be skin specific InstanceLogger.LogWarning("An error occured while adding accessories to a skin"); InstanceLogger.LogError(e); } //print heiarchy //RuneFoxMods.Utils.readheiarchy(modelObject); }
private static void clearModification(Modification modification, GameObject modelObject, AppliedModifications modifications) { //Destroy Dynamic Bones colliders if (modification.inst_DB_colliders != null) { foreach (var collider in modification.inst_DB_colliders) { Destroy(collider); } } //Remove Additions to Bone Arrays if (modification.affectsbasemodel) { var renderers = GetBaseSkinRenderers(modelObject); var oldBones = renderers[0].bones.ToList(); oldBones.RemoveRange(modification.boneIndex, modification.boneCount); foreach (var renderer in renderers) { renderer.bones = oldBones.ToArray(); } } //Destroy Dynamic Bones Component (Probably don't have to do this since it will be destroyed along with PrefabInstance if parented to it) Destroy(modifications.OtherModifications[0].inst_dynamicBone); //Destroy Armature Destroy(modifications.OtherModifications[0].inst_armature); //Destroy Prefab Instance Destroy(modifications.OtherModifications[0].instance); bool removed = modifications.OtherModifications.Remove(modification); if (!removed) { InstanceLogger.LogError("Skin Modification was not removed"); } }
////// Local Functions //////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /// <param name="modelObject">GameObject of ModelObject</param> /// <param name="modifications">List for Storing Modifctions</param> /// <param name="characterModel">Character Model of ModelObject</param> /// <param name="modification">Modification to be apllied</param> private static void ApplyModification(GameObject modelObject, CharacterModel characterModel, Modification modification, AppliedModifications modifications) { //Get aramture bone that new prefab will be parented to var bodyname = modification.bodyname; var parentname = modification.parentname; var parentBone = RuneFoxMods.Utils.FindChildInTree(modelObject.transform, parentname); //var parentBone = modelObject.transform.Find(RuneFoxMods.ChildHelper.GetPath(bodyname, parentname)); GameObject newPart; //we have to instantiate the prefabs in two different ways based on if they affect the model or not if (modification.affectsbasemodel) { //instantiate the model newPart = GameObject.Instantiate(modification.prefab, parentBone, false); newPart.name = RuneFoxMods.Utils.RemoveCloneNaming(newPart.name); modification.instance = newPart; modification.inst_armature = newPart; //the armature of the modifications that affect the base mode is the whole prefab /////////////////////////////////////////////////////////// /// Add Bones to Base Armature here var skinRenderers = GetBaseSkinRenderers(modelObject); var newBones = skinRenderers[0].bones.ToList();//assumption is that we find a skinrenderer here, if not then whoops var newBoneIndex = FindBoneIndex2(parentBone, newBones); //insert new bones into array at end of array var modBoneArray = BoneArrayBuilder(modification.instance.transform); newBones.InsertRange(newBoneIndex, modBoneArray); //add index and bonecount to modification modification.boneIndex = newBoneIndex; modification.boneCount = modBoneArray.Length; //assign bones to skin renderers foreach (var renderer in skinRenderers) { renderer.bones = newBones.ToArray(); } modifications.BaseModelModifications.Push(modification); /// Add Bones to Base Armature here /////////////////////////////////////////////////////////// } else { //instantiate it w/ model as parent newPart = GameObject.Instantiate(modification.prefab, modelObject.transform, false); newPart.name = RuneFoxMods.Utils.RemoveCloneNaming(newPart.name); modification.instance = newPart; var armature = GetArmature(newPart); //if (armature == null) // Debug.Log("Armature not found"); //else // Debug.Log("armature found: " + armature.name); //then parent the armature to the parentboned armature.transform.SetParent(parentBone, false); modification.inst_armature = armature.gameObject; } modification.instance = newPart; //TODO: add a way to load multiple DynamicBone Scripts for a single modification /////////////////////////////////////////////////////////// /// Add dynamic bones stuff here /// Things like DynamicBones Component, assigning values to dynamic bones component, adding DB_Colliders and editing them, etc. if (modification.dynamicBoneData != null) { //====================================== //Add Dynamic Bone Component DynamicBone DB = modification.instance.AddComponent <DynamicBone>(); modification.inst_dynamicBone = DB; //====================================== /// Add DynamicBones Colliders to other armature bones (Need to do this before Modifying Dynamic Bones component as we add them to the DB list during modification) List <DynamicBoneCollider> bonelist = new List <DynamicBoneCollider>(); foreach (var colliderData in modification.dynamicBoneData.m_Colliders) { var parent = RuneFoxMods.Utils.FindChildInTree(modelObject.transform, colliderData.m_parent_name); //var parent = modelObject.transform.Find(RuneFoxMods.ChildHelper.GetPath(bodyname, colliderData.m_parent_name)); var bonecollider = parent.gameObject.AddComponent <DynamicBoneCollider>(); bonecollider.m_Direction = colliderData.m_Direction; bonecollider.m_Center = colliderData.m_Center; bonecollider.m_Bound = colliderData.m_Bound; bonecollider.m_Radius = colliderData.m_Radius; bonecollider.m_Height = colliderData.m_Height; bonelist.Add(bonecollider); } modification.inst_DB_colliders = bonelist; //====================================== // Modify DynamicBones Component with data var root = RuneFoxMods.Utils.FindChildInTree(modification.inst_armature.transform, modification.dynamicBoneData.m_Root); DB.m_Root = root; DB.m_Damping = modification.dynamicBoneData.m_Damping; DB.m_DampingDistrib = modification.dynamicBoneData.m_DampingDistrib; DB.m_Elasticity = modification.dynamicBoneData.m_Elasticity; DB.m_ElasticityDistrib = modification.dynamicBoneData.m_ElasticityDistrib; DB.m_Stiffness = modification.dynamicBoneData.m_Stiffness; DB.m_StiffnessDistrib = modification.dynamicBoneData.m_StiffnessDistrib; DB.m_Inert = modification.dynamicBoneData.m_Inert; DB.m_InertDistrib = modification.dynamicBoneData.m_InertDistrib; DB.m_Radius = modification.dynamicBoneData.m_Radius; DB.m_RadiusDistrib = modification.dynamicBoneData.m_RadiusDistrib; DB.m_EndLength = modification.dynamicBoneData.m_EndLength; DB.m_EndOffset = modification.dynamicBoneData.m_EndOffset; DB.m_Gravity = modification.dynamicBoneData.m_Gravity; DB.m_Force = modification.dynamicBoneData.m_Force; DB.m_Colliders = bonelist; DB.m_Exclusions = new List <Transform>(); foreach (var exclude in modification.dynamicBoneData.m_Exclusions) { //NOTE: Assumption here is that the dynamic bone root is part of the new armature and we are only excluding bones located in root var transform = RuneFoxMods.Utils.FindChildInTree(root, exclude); if (transform != null) { DB.m_Exclusions.Add(transform); } else { Debug.Log("Tried to exclude a transform that could not be found"); } } DB.m_FreezeAxis = modification.dynamicBoneData.m_FreezeAxis; //TODO: Read DB and compare it to what's made in OG mod cause skirt is behaving oddly } /// Add dynamic bones stuff here /////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// /// Add renderers to the character's renderer list //get renderers var renderers = newPart.GetComponentsInChildren <SkinnedMeshRenderer>(true); //resize render array to account for new renderers Array.Resize(ref characterModel.baseRendererInfos, characterModel.baseRendererInfos.Length + renderers.Length); //NOTE: Need to save the number of renderers added to the character render info so we can remove them cleanly. Probably add this to modifications if (renderers.Length != 0) { int i = renderers.Length; foreach (var renderer in renderers) { //2 to add - 3 in //resize array to 5 //first is added at 5-2 (3) which is position 4 //second is added at 5-1 (4) which is position 5 //exits characterModel.baseRendererInfos[characterModel.baseRendererInfos.Length - i] = new CharacterModel.RendererInfo { renderer = renderers[renderers.Length - i], ignoreOverlays = false, defaultShadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On, defaultMaterial = renderer.sharedMaterial }; i--; //decrement i to reach the next renederer } } /// Add renderers to the character's renderer list /////////////////////////////////////////////////////////// //Push to applied modifications when done modifications.OtherModifications.Add(modification); }