/// <summary> /// Loads a blendshape from character card and sets it to the correct mesh /// </summary> /// <param name="data">The characters card data for this plugin</param> internal void LoadBlendShapes(PregnancyPlusData data) { if (data.meshBlendShape == null) { return; } if (PregnancyPlusPlugin.DebugLog.Value) { PregnancyPlusPlugin.Logger.LogInfo($" MeshBlendShape size > {data.meshBlendShape.Length/1024}KB "); } meshWithBlendShapes = new List <SkinnedMeshRenderer>(); //Unserialize the blendshape from characters card var meshBlendShapes = MessagePack.LZ4MessagePackSerializer.Deserialize <List <MeshBlendShape> >(data.meshBlendShape); if (meshBlendShapes == null || meshBlendShapes.Count <= 0) { return; } //For each stores meshBlendShape foreach (var meshBlendShape in meshBlendShapes) { //Loop through all meshes and find matching name var clothRenderers = PregnancyPlusHelper.GetMeshRenderers(ChaControl.objClothes, true); LoopMeshAndAddExistingBlendShape(clothRenderers, meshBlendShape, true); //do the same for body meshs var bodyRenderers = PregnancyPlusHelper.GetMeshRenderers(ChaControl.objBody, true); LoopMeshAndAddExistingBlendShape(bodyRenderers, meshBlendShape); } }
/// <summary> /// On user button click. Create blendshape from current belly state. Add it to infConfig so it will be saved to char card if the user chooses save scene /// </summary> /// <param name="temporary">If Temporary, the blendshape will not be saved to char card</param> /// <returns>boolean true if any blendshapes were created</returns> internal bool OnCreateBlendShapeSelected(bool temporary = false) { if (PregnancyPlusPlugin.DebugLog.Value) { PregnancyPlusPlugin.Logger.LogInfo($" "); } if (PregnancyPlusPlugin.DebugLog.Value) { PregnancyPlusPlugin.Logger.LogInfo($" OnCreateBlendShapeSelected "); } var meshBlendShapes = new List <MeshBlendShape>(); meshWithBlendShapes = new List <SkinnedMeshRenderer>(); //Get all cloth renderes and attempt to create blendshapes from preset inflatedVerticies var clothRenderers = PregnancyPlusHelper.GetMeshRenderers(ChaControl.objClothes); meshBlendShapes = LoopAndCreateBlendShape(clothRenderers, meshBlendShapes, true); //do the same for body meshs var bodyRenderers = PregnancyPlusHelper.GetMeshRenderers(ChaControl.objBody); meshBlendShapes = LoopAndCreateBlendShape(bodyRenderers, meshBlendShapes); //Save any meshBlendShapes to card if (!temporary) { AddBlendShapesToData(meshBlendShapes); } //Reset belly size to 0 so the blendshape can be used with out interference PregnancyPlusGui.ResetSlider(PregnancyPlusGui.inflationSize, 0); //Append the smrs that have new blendspahes to the GUI to be seen blendShapeGui.OnSkinnedMeshRendererBlendShapesCreated(meshWithBlendShapes); return(meshBlendShapes.Count > 0); }
/// <summary> /// Triggers belly mesh inflation for the current ChaControl for any active meshs (not hidden clothes) /// It will check the inflationSize dictionary for a valid value (last set via config slider or MeshInflate(value)) /// If size 0 is used it will clear all active mesh inflations /// This will not run twice for the same parameters, a change of config value is required /// </summary> /// <param name="checkForNewMesh">Lets you force bypass the check for values changed to check for new meshes</param> /// <param name="freshStart">Will recalculate verts like a first time run</param> /// <param name="pluginConfigSliderChanged">Will treat as if some slider values changed, which they did in global plugin config</param> /// <returns>Will return True if the mesh was altered and False if not</returns> public bool MeshInflate(bool checkForNewMesh = false, bool freshStart = false, bool pluginConfigSliderChanged = false) { if (ChaControl.objBodyBone == null) { return(false); //Make sure chatacter objs exists first } if (!PregnancyPlusPlugin.AllowMale.Value && ChaControl.sex == 0) { return(false); // Only female characters, unless plugin config says otherwise } var sliderHaveChanged = NeedsMeshUpdate(pluginConfigSliderChanged); //Only continue if one of the config values changed if (!sliderHaveChanged) { //Only stop here, if no recalculation needed if (!freshStart && !checkForNewMesh) { return(false); } } ResetInflation(); if (!AllowedToInflate()) { return(false); //if outside studio/maker, make sure StoryMode is enabled first } if (!infConfig.GameplayEnabled) { return(false); //Only if gameplay enabled } //Resets all stored vert values, so the script will have to recalculate all from base body if (freshStart) { CleanSlate(); } //Only continue when size above 0 if (infConfig.inflationSize <= 0) { infConfigHistory.inflationSize = 0; return(false); } if (PregnancyPlusPlugin.DebugLog.Value) { PregnancyPlusPlugin.Logger.LogInfo($" ---------- "); } if (PregnancyPlusPlugin.DebugLog.Value) { PregnancyPlusPlugin.Logger.LogInfo($" inflationSize > {infConfig.inflationSize} for {charaFileName} "); } //Get the measurements that determine the base belly size var hasMeasuerments = MeasureWaistAndSphere(ChaControl); if (!hasMeasuerments) { PregnancyPlusPlugin.errorCodeCtrl.LogErrorCode(ChaControl.chaID, ErrorCode.PregPlus_BadMeasurement, $"Could not get belly measurements from character"); return(false); } var anyMeshChanges = false; //Get and apply all clothes render mesh changes var clothRenderers = PregnancyPlusHelper.GetMeshRenderers(ChaControl.objClothes); anyMeshChanges = LoopAndApplyMeshChanges(clothRenderers, sliderHaveChanged, anyMeshChanges, true); //do the same for body meshs var bodyRenderers = PregnancyPlusHelper.GetMeshRenderers(ChaControl.objBody, true); anyMeshChanges = LoopAndApplyMeshChanges(bodyRenderers, sliderHaveChanged, anyMeshChanges); //If any changes were applied, updated the last used shape for the Restore GUI button if (infConfig.HasAnyValue()) { PregnancyPlusPlugin.lastBellyState = (PregnancyPlusData)infConfig.Clone();//CLone so we don't accidently overwright the lastState later } //Update config history when mesh changes were made if (anyMeshChanges) { infConfigHistory = (PregnancyPlusData)infConfig.Clone(); } return(anyMeshChanges); }