// Update //-------------------------------------- public void Update(float tDelta) { if (_childMeshGroup == null) { return; } _childMeshGroup.UpdateRenderUnits(tDelta, false); }
// Update //-------------------------------------- public void Update(float tDelta, bool isBoneIKMatrix, bool isBoneIKRigging) { if (_childMeshGroup == null) { return; } _childMeshGroup.SetBoneIKEnabled(isBoneIKMatrix, isBoneIKRigging); _childMeshGroup.UpdateRenderUnits(tDelta, false); _childMeshGroup.SetBoneIKEnabled(false, false); }
/// <summary> /// [Editor] 모든 애니메이션 처리를 포함한 MeshGroup 업데이트를 한다. /// </summary> /// <param name="isForce"></param> /// <param name="tDelta"></param> /// <param name="isUpdateVertsAlways">단순 재생시에는 False, 작업시에는 True로 설정한다.</param> public void UpdateMeshGroup_Editor(bool isForce, float tDelta, bool isUpdateVertsAlways, bool isDepthChanged = false) { if (_targetMeshGroup == null) { //Debug.LogError("Update Failed : No Target Mesh Group"); return; } if (isForce) { //_targetMeshGroup.SetAllRenderUnitForceUpdate(); _targetMeshGroup.RefreshForce(isDepthChanged, tDelta); } else { _targetMeshGroup.UpdateRenderUnits(tDelta, isUpdateVertsAlways); } }
// Functions //---------------------------------------------- public Texture2D RenderToTexture(apMeshGroup meshGroup, int winPosX, int winPosY, int srcSizeWidth, int srcSizeHeight, int dstSizeWidth, int dstSizeHeight, Color clearColor) { if (_editor == null) { return(null); } //apGL의 Window Size를 바꾸어준다. int rtSizeWidth = ((int)_editor.position.width); int rtSizeHeight = ((int)_editor.position.height); //winPosY -= 10; int guiOffsetX = apGL._posX_NotCalculated; int guiOffsetY = apGL._posY_NotCalculated; int clipPosX = winPosX - (srcSizeWidth / 2); int clipPosY = winPosY - (srcSizeHeight / 2); clipPosX += guiOffsetX; clipPosY += guiOffsetY + 15; int clipPosX_Right = clipPosX + srcSizeWidth; int clipPosY_Bottom = clipPosY + srcSizeHeight; if (clipPosX < 0) { clipPosX = 0; } if (clipPosY < 0) { clipPosY = 0; } if (clipPosX_Right > rtSizeWidth) { clipPosX_Right = rtSizeWidth; } if (clipPosY_Bottom > rtSizeHeight) { clipPosY_Bottom = rtSizeHeight; } int clipWidth = (clipPosX_Right - clipPosX); int clipHeight = (clipPosY_Bottom - clipPosY); if (clipWidth <= 0 || clipHeight <= 0) { Debug.LogError("RenderToTexture Failed : Clip Area is over Screen"); return(null); } meshGroup.RefreshForce(); meshGroup.UpdateRenderUnits(0.0f, true); //Pass-1. 일반 + MaskParent를 Alpha2White 렌더링. 이걸로 나중에 알파 채널용 텍스쳐를 만든다. //-------------------------------------------------------------------------------------------------------- _renderTexture_GrayscaleAlpha = RenderTexture.GetTemporary(rtSizeWidth, rtSizeHeight, 8, RenderTextureFormat.ARGB32); _renderTexture_GrayscaleAlpha.antiAliasing = 1; _renderTexture_GrayscaleAlpha.wrapMode = TextureWrapMode.Clamp; RenderTexture.active = null; RenderTexture.active = _renderTexture_GrayscaleAlpha; //기본 Color maskClearColor = new Color(clearColor.a, clearColor.a, clearColor.a, 1.0f); GL.Clear(false, true, maskClearColor, 0.0f); //변경 : Mac에서도 작동 하려면.. apGL.DrawBoxGL(Vector2.zero, 50000, 50000, maskClearColor, false, true); //<<이걸로 배경을 깔자 GL.Flush(); //System.Threading.Thread.Sleep(50); for (int iUnit = 0; iUnit < meshGroup._renderUnits_All.Count; iUnit++) { apRenderUnit renderUnit = meshGroup._renderUnits_All[iUnit]; if (renderUnit._unitType == apRenderUnit.UNIT_TYPE.Mesh) { if (renderUnit._meshTransform != null) { if (renderUnit._meshTransform._isClipping_Parent) { if (renderUnit._isVisible) { //RenderTexture.active = _renderTexture_GrayscaleAlpha; apGL.DrawRenderUnit_Basic_Alpha2White(renderUnit); } } else if (renderUnit._meshTransform._isClipping_Child) { //Pass //Alpha 렌더링에서 Clipping Child는 제외한다. 어차피 Parent의 Alpha보다 많을 수 없으니.. } else { if (renderUnit._isVisible) { //RenderTexture.active = _renderTexture_GrayscaleAlpha; apGL.DrawRenderUnit_Basic_Alpha2White(renderUnit); } } } } } System.Threading.Thread.Sleep(5); Texture2D resultTex_SrcSize_Alpha = new Texture2D(srcSizeWidth, srcSizeHeight, TextureFormat.ARGB32, false); resultTex_SrcSize_Alpha.ReadPixels(new Rect(clipPosX, clipPosY, clipWidth, clipHeight), 0, 0); resultTex_SrcSize_Alpha.Apply(); //Pass-2. 기본 렌더링 //-------------------------------------------------------------------------------------------------------- //1. Clip Parent의 MaskTexture를 미리 구워서 Dictionary에 넣는다. Dictionary <apRenderUnit, Texture2D> bakedClipMaskTextures = new Dictionary <apRenderUnit, Texture2D>(); //Debug.Log("-------------------------------------------------------------"); //Debug.Log("RenderTextureSize : " + rtSizeWidth + " x " + rtSizeHeight); //Debug.Log("Capture Size : " + imageSizeWidth + " x " + imageSizeHeight); //Debug.Log("Capture Pos : " + winPosX + ", " + winPosY); //Debug.LogError("GL Size : " + apGL._totalEditorWidth + " x " + apGL._totalEditorHeight); for (int iUnit = 0; iUnit < meshGroup._renderUnits_All.Count; iUnit++) { apRenderUnit renderUnit = meshGroup._renderUnits_All[iUnit]; if (renderUnit._unitType == apRenderUnit.UNIT_TYPE.Mesh) { if (renderUnit._meshTransform != null) { if (renderUnit._meshTransform._isClipping_Parent) { if (renderUnit._isVisible) { Texture2D clipMaskTex = apGL.GetMaskTexture_ClippingParent(renderUnit); if (clipMaskTex != null) { bakedClipMaskTextures.Add(renderUnit, clipMaskTex); } else { Debug.LogError("Clip Testure Bake Failed"); } } } } } } System.Threading.Thread.Sleep(5); _renderTexture = RenderTexture.GetTemporary(rtSizeWidth, rtSizeHeight, 8, RenderTextureFormat.ARGB32); _renderTexture.antiAliasing = 1; _renderTexture.wrapMode = TextureWrapMode.Clamp; RenderTexture.active = null; RenderTexture.active = _renderTexture; Color opaqueClearColor = new Color(clearColor.r * clearColor.a, clearColor.g * clearColor.a, clearColor.b * clearColor.a, 1.0f); //GL.Clear(true, true, clearColor, -100.0f);//이전 GL.Clear(false, true, opaqueClearColor, 0.0f); //변경 : Mac에서도 작동 하려면.. apGL.DrawBoxGL(Vector2.zero, 50000, 50000, opaqueClearColor, false, true); //<<이걸로 배경을 깔자 GL.Flush(); //System.Threading.Thread.Sleep(50); for (int iUnit = 0; iUnit < meshGroup._renderUnits_All.Count; iUnit++) { apRenderUnit renderUnit = meshGroup._renderUnits_All[iUnit]; if (renderUnit._unitType == apRenderUnit.UNIT_TYPE.Mesh) { if (renderUnit._meshTransform != null) { if (renderUnit._meshTransform._isClipping_Parent) { if (renderUnit._isVisible) { if (bakedClipMaskTextures.ContainsKey(renderUnit)) { apGL.DrawRenderUnit_ClippingParent_Renew_WithoutRTT(renderUnit, renderUnit._meshTransform._clipChildMeshes, bakedClipMaskTextures[renderUnit]); } ////RenderTexture.active = _renderTexture;//<<클리핑 뒤에는 다시 연결해줘야한다. } } else if (renderUnit._meshTransform._isClipping_Child) { //Pass } else { if (renderUnit._isVisible) { RenderTexture.active = _renderTexture; apGL.DrawRenderUnit_Basic(renderUnit); } } } } } System.Threading.Thread.Sleep(5); Texture2D resultTex_SrcSize = new Texture2D(srcSizeWidth, srcSizeHeight, TextureFormat.ARGB32, false); resultTex_SrcSize.ReadPixels(new Rect(clipPosX, clipPosY, clipWidth, clipHeight), 0, 0); //Texture2D resultTex_SrcSize = new Texture2D(_renderTexture.width, _renderTexture.height, TextureFormat.ARGB32, false); //resultTex_SrcSize.ReadPixels(new Rect(0, 0, _renderTexture.width, _renderTexture.height), 0, 0); resultTex_SrcSize.Apply(); //System.Threading.Thread.Sleep(50); RenderTexture.active = null; RenderTexture.ReleaseTemporary(_renderTexture_GrayscaleAlpha); RenderTexture.ReleaseTemporary(_renderTexture); //<< //UnityEngine.Object.DestroyImmediate(_renderTexture); _renderTexture = null; _renderTexture_GrayscaleAlpha = null; Texture2D resultTex_DstSize = new Texture2D(dstSizeWidth, dstSizeHeight, TextureFormat.ARGB32, false); Color color_RGB = Color.black; Color color_A = Color.black; for (int iY = 0; iY < dstSizeHeight; iY++) { for (int iX = 0; iX < dstSizeWidth; iX++) { float u = (float)iX / (float)dstSizeWidth; float v = (float)iY / (float)dstSizeHeight; color_RGB = resultTex_SrcSize.GetPixelBilinear(u, v); color_A = resultTex_SrcSize_Alpha.GetPixelBilinear(u, v); resultTex_DstSize.SetPixel(iX, iY, new Color(color_RGB.r, color_RGB.g, color_RGB.b, color_A.r)); //resultTex_DstSize.SetPixel(iX, iY, new Color(color_A.r, color_A.g, color_A.b, 1)); } } System.Threading.Thread.Sleep(5); //기존 크기의 이미지는 삭제 UnityEngine.Object.DestroyImmediate(resultTex_SrcSize); UnityEngine.Object.DestroyImmediate(resultTex_SrcSize_Alpha); resultTex_DstSize.Apply(); return(resultTex_DstSize); }
/// <summary> /// GIF Animation을 만든다. /// </summary> /// <param name="filePath"></param> /// <param name="meshGroup"></param> /// <param name="animClip"></param> /// <param name="loopCount"></param> /// <param name="winPosX"></param> /// <param name="winPosY"></param> /// <param name="srcSizeWidth"></param> /// <param name="srcSizeHeight"></param> /// <param name="dstSizeWidth"></param> /// <param name="dstSizeHeight"></param> /// <param name="clearColor"></param> /// <param name="quality">1 ~ 256</param> /// <returns></returns> public bool MakeGIFAnimation(string filePath, apMeshGroup meshGroup, apAnimClip animClip, int loopCount, int winPosX, int winPosY, int srcSizeWidth, int srcSizeHeight, int dstSizeWidth, int dstSizeHeight, Color clearColor, int quality) { if (_editor == null || _editor._portrait == null || meshGroup == null || animClip == null) { return(false); } int startFrame = animClip.StartFrame; int endFrame = animClip.EndFrame; if (endFrame < startFrame) { endFrame = startFrame; } if (loopCount < 1) { loopCount = 1; } //모든 AnimClip 정지 for (int i = 0; i < _editor._portrait._animClips.Count; i++) { _editor._portrait._animClips[i].Stop_Editor(); } _editor._portrait._animPlayManager.Stop_Editor(); _editor._portrait._animPlayManager.SetAnimClip_Editor(animClip); meshGroup.RefreshForce(); int curFrame = startFrame; bool isLoop = animClip.IsLoop; //Loop라면 마지막 프레임을 생략한다. int lastFrame = endFrame; if (isLoop) { lastFrame = endFrame - 1; } if (lastFrame < startFrame) { lastFrame = startFrame; } float secPerFrame = 1.0f / (float)animClip.FPS; FileStream fs = null; try { fs = new FileStream(filePath, FileMode.Create, FileAccess.Write); _ngif.WriteHeader(fs); _ngif.SetGIFSetting((int)((secPerFrame * 100.0f) + 0.5f), 0, dstSizeWidth, dstSizeHeight); //WriteString("GIF89a", fs); // header //_gifDelay = (int)((secPerFrame * 100.0f) + 0.5f);//Delay //_gifRepeatCount = 0;//반복 //_gifWidth = dstSizeWidth; //_gifHeight = dstSizeHeight; //_gifPixels = null; //_gifIndexedPixels = null; //_gifColorDepth = 0; //_gifColorTab = null; //_gifPalSize = 7; //for (int i = 0; i < _gifUsedEntry.Length; i++) //{ // _gifUsedEntry[i] = false; //} bool isFirstFrame = true; //애니메이션을 돌면서 Bake를 한다. for (int iLoop = 0; iLoop < loopCount; iLoop++) { curFrame = startFrame; while (true) { animClip.SetFrame_Editor(curFrame); //메시가 자동으로 업데이트를 한다. meshGroup.UpdateRenderUnits(secPerFrame, true); Texture2D bakeImage = RenderToTexture(meshGroup, winPosX, winPosY, srcSizeWidth, srcSizeHeight, dstSizeWidth, dstSizeHeight, clearColor); _ngif.AddFrame(bakeImage, fs, isFirstFrame, quality); isFirstFrame = false; UnityEngine.Object.DestroyImmediate(bakeImage); curFrame++; if (curFrame > lastFrame) { break; } } } _ngif.Finish(fs); fs.Close(); fs = null; return(true); } catch (Exception ex) { Debug.LogError("GIF Exception : " + ex); } if (fs != null) { fs.Close(); fs = null; } return(false); }