public Color SampleRenderTexture(Vector2 uv) { RenderTexture curRT = RenderTexture.active; // Debug.Log("Sampling Render Texture"); PainterCamera rtp = PainterCamera.Inst; int size = PainterCamera.renderTextureSize / 4; RenderTexture.active = renderTexture ?? rtp.GetDownscaledBigRT(size, size); if (sampler == null) { sampler = new Texture2D(8, 8); } UVto01(ref uv); if (renderTexture == null) { uv.y = 1 - uv.y; // For some reason sampling is mirrored around Y axiz for BigRenderTexture (?) } uv *= RenderTexture.active.width; sampler.ReadPixels(new Rect(uv.x, uv.y, 1, 1), 0, 0); RenderTexture.active = curRT; var pix = sampler.GetPixel(0, 0); if (PainterCamera.Inst.isLinearColorSpace) { pix = pix.linear; } return(pix); }
public virtual bool PEGI() { PlaytimePainter p = PlaytimePainter.inspectedPainter; if (p == null) { "No Painter Detected".nl(); return(false); } if ((p.skinnedMeshRendy != null) && (pegi.Click("Update Collider from Skinned Mesh"))) { p.UpdateColliderForSkinnedMesh(); } pegi.newLine(); ImageData id = p.ImgData; bool changed = false; bool cpuBlit = id.destination == TexTarget.Texture2D; pegi.newLine(); changed |= p.PreviewShaderToggle_PEGI(); if ((PainterCamera.GotBuffers() || (id.renderTexture != null)) && (id.texture2D != null)) { if ((cpuBlit ? icon.CPU : icon.GPU).Click( cpuBlit ? "Switch to Render Texture" : "Switch to Texture2D", 45)) { p.UpdateOrSetTexTarget(cpuBlit ? TexTarget.RenderTexture : TexTarget.Texture2D); SetSupportedFor(cpuBlit, id.renderTexture == null); changed = true; } } if (cpuBlit) { bool smooth = _type(cpuBlit) != BrushTypePixel.Inst.index; if (pegi.toggle(ref smooth, icon.Round, icon.Square, "Smooth/Pixels Brush", 45)) { changed = true; TypeSet(cpuBlit, smooth ? (BrushType)BrushTypeNormal.Inst : (BrushType)BrushTypePixel.Inst); } } pegi.newLine(); #if UNITY_EDITOR if (Tools.current != Tool.None) { Msg.LockToolToUseTransform.Get().writeWarning(); if (Msg.HideTransformTool.Get().Click().nl()) { PlaytimePainter.HideUnityTool(); } } #endif if //( (!p.IsOriginalShader) // && (cfg.moreOptions)) { changed |= pegi.toggle(ref Cfg.previewAlphaChanel, "Preview Enabled Chanels", 130); } if (Mode_Type_PEGI()) { if (Type(cpuBlit) == BrushTypeDecal.Inst) { MaskSet(BrushMask.A, true); } changed = true; } if (p.terrain != null) { if ((p.ImgData != null) && ((p.IsTerrainHeightTexture())) && (p.IsOriginalShader)) { pegi.writeWarning(" You need to use Preview Shader to see changes"); } pegi.newLine(); if ((p.terrain != null) && (pegi.Click("Update Terrain").nl())) { p.UpdateShaderGlobals(); } } return(changed); }
public override void PaintRenderTexture(PlaytimePainter pntr, BrushConfig br, StrokeVector st) { BeforeStroke(pntr, br, st); // Vector2 outb = new Vector2(Mathf.Floor(st.uvTo.x), Mathf.Floor(st.uvTo.y)); // st.uvTo -= outb; // st.uvFrom -= outb; Vector2 delta_uv = st.Delta_uv;//uv - st.uvFrom;//.Previous_uv; float magn = delta_uv.magnitude; var id = pntr.ImgData; float width = br.Size(false) / ((float)id.width) * 4; //const float followPortion = 0.5f; //float follow = width; float trackPortion = (delta_uv.magnitude - width * 0.5f) * 0.25f; if ((trackPortion > 0) || (st.mouseUp)) { if (st.firstStroke) { previousDirectionLazy = st.previousDelta = delta_uv; LazySpeedDynamic = delta_uv.magnitude; LazyAngleSmoothed = 0; // Debug.Log("First stroke"); } float angle = Mathf.Deg2Rad * Vector2.Angle(st.previousDelta, delta_uv); bool smooth = angle < Mathf.PI * 0.5f; if ((st.CrossedASeam()) && (magn > previousDirectionLazy.magnitude * 8)) { // Debug.Log("Crossed a seam"); st.mouseUp = true; st.uvTo = st.uvFrom;// painter.Previous_uv; delta_uv = Vector2.zero; smooth = false; } previousDirectionLazy = delta_uv; if (!st.mouseUp) { if (smooth) { float clockwise = Vector3.Cross(st.previousDelta, delta_uv).z > 0 ? 1 : -1; float sin = Mathf.Sin(angle) * clockwise; float maxSinus = 8; if (Mathf.Abs(LazyAngleSmoothed) > Mathf.Abs(sin)) { LazyAngleSmoothed = sin; } else { LazyAngleSmoothed = Mathf.Lerp(LazyAngleSmoothed, sin, 0.2f); } sin = LazyAngleSmoothed; if ((sin * sin > maxSinus * maxSinus) || ((sin > 0) != (maxSinus > 0))) { float absSin = Mathf.Abs(sin); float absNSin = Mathf.Abs(maxSinus); if (absSin < absNSin) { maxSinus = maxSinus * absSin / absNSin; } st.uvTo = st.uvFrom + st.previousDelta.normalized.Rotate(maxSinus * clockwise) * trackPortion; LazySpeedDynamic = trackPortion; } else { LazySpeedDynamic = Mathf.Min(delta_uv.magnitude * 0.5f, Mathf.Lerp(LazySpeedDynamic, delta_uv.magnitude * 0.5f, 0.001f)); LazySpeedDynamic = Mathf.Max(trackPortion, LazySpeedDynamic); st.uvTo = st.uvFrom + st.previousDelta.normalized.Rotate(sin) * LazySpeedDynamic; } } else { LazySpeedDynamic = delta_uv.magnitude; LazyAngleSmoothed = 0; st.uvTo = st.uvFrom + delta_uv.normalized * trackPortion; } } PainterCamera r = TexMGMT; //RenderTexturePainter.inst.RenderLazyBrush(painter.Previous_uv, uv, brush.speed * 0.05f, painter.curImgData, brush, painter.LmouseUP, smooth ); if (TexMGMT.BigRT_pair == null) { TexMGMT.UpdateBuffersState(); } float meshWidth = br.StrokeWidth(id.width, false); //.Size(false) / ((float)id.width) * 2 * rtp.orthoSize; Transform tf = Rtbrush; Vector2 direction = st.Delta_uv; //uvTo - uvFrom; bool isTail = st.firstStroke; //(!previousTo.Equals(uvFrom)); if ((!isTail) && (!smooth)) { var st2 = new StrokeVector(st) { firstStroke = false }; r.ShaderPrepareStroke(br, br.speed * 0.05f, id, st2, pntr); Vector3 junkPoint = st.uvFrom + st.previousDelta * 0.01f; BrushMesh = brushMeshGenerator.inst().GetStreak(UvToPosition(st.uvFrom), UvToPosition(junkPoint), meshWidth, true, false); tf.localScale = Vector3.one; tf.localRotation = Quaternion.identity; tf.localPosition = new Vector3(0, 0, 10); r.Render();//Render_UpdateSecondBufferIfUsing(id); st.uvFrom = junkPoint; isTail = true; } r.ShaderPrepareStroke(br, br.speed * 0.05f, id, st, pntr); BrushMesh = brushMeshGenerator.inst().GetStreak(UvToPosition(st.uvFrom), UvToPosition(st.uvTo), meshWidth, st.mouseUp, isTail); tf.localScale = Vector3.one; tf.localRotation = Quaternion.identity; tf.localPosition = new Vector3(0, 0, 10); st.previousDelta = direction; r.Render(); AfterStroke(pntr, br, st); } }
public override void OnInspectorGUI() { #if !NO_PEGI bool changes = false; painter = (PlaytimePainter)target; if (painter.gameObject.IsPrefab()) { "Inspecting a prefab.".nl(); return; } PainterCamera rtp = PainterCamera.Inst; if (!Cfg) { "No Config Detected".nl(); return; } ef.start(serializedObject); if (!PlaytimePainter.IsCurrent_Tool()) { if (pegi.Click(icon.Off, "Click to Enable Tool", 25)) { PlaytimeToolComponent.enabledTool = typeof(PlaytimePainter);// customTools.Painter; CloseAllButThis(painter); painter.CheckPreviewShader(); PlaytimePainter.HideUnityTool(); } painter.gameObject.end(); return; } else { if ((IsCurrentTool() && (painter.terrain != null) && (Application.isPlaying == false) && (UnityEditorInternal.InternalEditorUtility.GetIsInspectorExpanded(painter.terrain) == true)) || (pegi.Click(icon.On.getIcon(), "Click to Disable Tool", 25))) { PlaytimeToolComponent.enabledTool = null; //customTools.Disabled; MeshManager.Inst.DisconnectMesh(); painter.SetOriginalShaderOnThis(); painter.UpdateOrSetTexTarget(TexTarget.Texture2D); PlaytimePainter.RestoreUnityTool(); } } painter.InitIfNotInited(); ImageData image = painter.ImgData; Texture tex = painter.GetTextureOnMaterial(); if ((!painter.meshEditing) && ((tex != null) && (image == null)) || ((image != null) && (tex == null)) || ((image != null) && (tex != image.texture2D) && (tex != image.CurrentTexture()))) painter.textureWasChanged = true; changes = painter.PEGI_MAIN(); image = painter.ImgData; if (painter.meshEditing || (PainterStuff.IsNowPlaytimeAndDisabled)) { painter.gameObject.end(); return; } if ((painter.meshRenderer != null || painter.terrain != null) && !Cfg.showConfig) { if (!painter.LockTextureEditing) { ef.newLine(); if (!painter.IsTerrainControlTexture()) { string Orig = ""; if (image.texture2D != null) { Orig = image.texture2D.GetPathWithout_Assets_Word(); if ((pegi.Click(icon.Load, "Will reload " + Orig, 25))) { painter.ForceReimportMyTexture(Orig); image.SaveName = image.texture2D.name; GUI.FocusControl("dummy"); if (painter.terrain != null) painter.UpdateShaderGlobals(); } } "Texture Name: ".edit(70, ref image.SaveName); if (image.texture2D != null) { string Dest = painter.GenerateTextureSavePath(); bool existsAtDestination = painter.TextureExistsAtDestinationPath(); bool originalExists = (Orig != null); bool sameTarget = originalExists && (Orig.Equals(Dest)); bool sameTextureName = originalExists && image.texture2D.name.Equals(image.SaveName); if ((existsAtDestination == false) || sameTextureName) { if (ef.Click(Icons_MGMT.getIcon(sameTextureName ? icon.Save : icon.SaveAsNew), (sameTextureName ? "Will Update " + Orig : "Will save as " + Dest), 25)) { if (sameTextureName) painter.RewriteOriginalTexture(); else painter.SaveTextureAsAsset(false); painter.OnChangedTexture_OnMaterial(); } } else if (existsAtDestination && (pegi.Click(icon.Save, "Will replace " + Dest, 25))) painter.SaveTextureAsAsset(false); ef.newLine(); if ((!sameTarget) && (!sameTextureName) && (string.IsNullOrEmpty(Orig) == false) && (ef.Click("Replace", "Will replace " + Orig + " with " + Dest))) painter.RewriteOriginalTexture_Rename(image.SaveName); } } ef.newLine(); } ef.newLine(); pegi.Space(); pegi.newLine(); var mats = painter.GetMaterials(); if ((mats != null) && (mats.Length > 0)) { int sm = painter.selectedSubmesh; if (pegi.select(ref sm, mats)) { painter.SetOriginalShaderOnThis(); painter.selectedSubmesh = sm; painter.OnChangedTexture_OnMaterial(); image = painter.ImgData; painter.CheckPreviewShader(); } } Material mater = painter.Material; if (pegi.edit(ref mater)) painter.Material = mater; if (icon.NewMaterial.Click("Instantiate Material", 25).nl()) { changes = true; painter.InstantiateMaterial(true); } // pegi.newLine(); if ((mats != null) && (mats.Length > 1)) "Auto Select Material:".toggle("Material will be changed based on the submesh you are painting on", 120, ref painter.autoSelectMaterial_byNumberOfPointedSubmesh).nl(); pegi.nl(); ef.Space(); ef.newLine(); // pegi.write("Tex:", "Texture field on the material", 30); if (painter.SelectTexture_PEGI()) { image = painter.ImgData; if (image == null) painter.nameHolder = painter.gameObject.name + "_" + painter.MaterialTexturePropertyName; } if (image != null) painter.UpdateTylingFromMaterial(); TextureSetterField(); if ((painter.IsTerrainControlTexture() == false)) { bool isTerrainHeight = painter.IsTerrainHeightTexture(); int texScale = (!isTerrainHeight) ? ((int)Mathf.Pow(2, PainterCamera.Data.selectedSize + minPow)) : (painter.terrain.terrainData.heightmapResolution - 1); List<string> texNames = painter.GetMaterialTextureNames(); if (texNames.Count > painter.SelectedTexture) { string param = painter.MaterialTexturePropertyName; if (pegi.Click(icon.NewTexture, (image == null) ? "Create new texture2D for " + param : "Replace " + param + " with new Texture2D " + texScale + "*" + texScale, 25).nl()) { changes = true; if (isTerrainHeight) painter.CreateTerrainHeightTexture(painter.nameHolder); else painter.CreateTexture2D(texScale, painter.nameHolder, Cfg.newTextureIsColor); } if ((image == null) && (Cfg.moreOptions) && ("Create Render Texture".Click())) { changes = true; painter.CreateRenderTexture(texScale, painter.nameHolder); } if ((image != null) && (Cfg.moreOptions)) { if ((image.renderTexture == null) && ("Add Render Tex".Click())) { changes = true; image.AddRenderTexture(); } if (image.renderTexture != null) { if ("Replace RendTex".Click("Replace " + param + " with Rend Tex size: " + texScale)) { changes = true; painter.CreateRenderTexture(texScale, painter.nameHolder); } if ("Remove RendTex".Click().nl()) { changes = true; if (image.texture2D != null) { painter.UpdateOrSetTexTarget(TexTarget.Texture2D); image.renderTexture = null; } else { painter.RemoveTextureFromMaterial(); //SetTextureOnMaterial(null); } } } } } else "No Material's Texture selected".nl(); pegi.nl(); if (image == null) "_Name:".edit("Name for new texture", 40, ref painter.nameHolder).nl(); if (!isTerrainHeight) { "Color:".toggle("Will the new texture be a Color Texture", 40, ref Cfg.newTextureIsColor); ef.write("Size:", "Size of the new Texture", 40); if ((texSizes == null) || (texSizes.Length != range)) { texSizes = new string[range]; for (int i = 0; i < range; i++) texSizes[i] = Mathf.Pow(2, i + minPow).ToString(); } ef.select(ref PainterCamera.Data.selectedSize, texSizes, 60); } ef.newLine(); } ef.newLine(); ef.tab(); ef.newLine(); List<ImageData> recentTexs; string texName = painter.MaterialTexturePropertyName; if ((texName != null) && (PainterCamera.Data.recentTextures.TryGetValue(texName, out recentTexs)) && ((recentTexs.Count > 1) || (painter.ImgData == null))) { ef.write("Recent Texs:", 60); ImageData tmp = painter.ImgData;//.exclusiveTexture(); if (pegi.select(ref tmp, recentTexs)) { painter.ChangeTexture(tmp.ExclusiveTexture()); changes = true; } } ef.Space(); ef.newLine(); ef.Space(); } if (changes) painter.Update_Brush_Parameters_For_Preview_Shader(); painter.gameObject.end(); #endif }
public override bool PEGI() { bool changed = base.PEGI(); PainterCamera rtp = PainterCamera.Inst; BrushConfig brush = brushConfig; if (!PainterStuff.IsNowPlaytimeAndDisabled) { "Plugins".write_List(rtp.Plugins, ref rtp.browsedPlugin); if ("Find New Plugins".Click()) { rtp.RefreshPlugins(); } if ("Clear Data".Click().nl()) { rtp.DeletePlugins(); rtp.RefreshPlugins(); } } pegi.newLine(); bool gotDefine = UnityHelperFunctions.GetDefine(enablePainterForBuild); if ("Enable Painter for Playtime & Build".toggle(ref gotDefine).nl()) { UnityHelperFunctions.SetDefine(enablePainterForBuild, gotDefine); } if (gotDefine && "Enable PlayTime UI".toggle(ref enablePainterUIonPlay).nl()) { MeshManager.Inst.DisconnectMesh(); } if (!PainterStuff.IsNowPlaytimeAndDisabled) { if (Painter && Painter.meshEditing == false) { if ("More options".toggle(80, ref moreOptions).nl()) { showConfig = false; } "CPU blit repaint delay".nl("Delay for video memory update when painting to Texture2D", 140); changed |= pegi.edit(ref brush.repaintDelay, 0.01f, 0.5f).nl(); changed |= "Don't update mipmaps:".toggle("May increase performance, but your changes may not disaplay if you are far from texture.", 150, ref brush.DontRedoMipmaps).nl(); var id = Painter.ImgData; if (id != null) { changed |= id.PEGI(); } "Disable Non-Mesh Colliders in Play Mode:".toggle(ref disableNonMeshColliderInPlayMode).nl(); } if ("Lists".foldout(ref inspectLists).nl()) { changed |= DatasPEGI(); } "Teaching Notifications".toggle("will show whatever you ae pressing on the screen.", 140, ref ShowTeachingNotifications).nl(); "Save Textures To:".edit(110, ref texturesFolderName).nl(); "_Atlas Textures Sub folder".edit(150, ref atlasFolderName).nl(); "Save Materials To:".edit(110, ref materialsFolderName).nl(); "Save Meshes To:".edit(110, ref meshesFolderName).nl(); } #if UNITY_EDITOR if (icon.Discord.Click("Join Discord", 64)) { PlaytimePainter.Open_Discord(); } if (icon.Docs.Click("Open Asset Documentation", 64)) { PlaytimePainter.OpenWWW_Documentation(); } if (icon.Email.Click("Report a bug / send suggestion / ask question.", 64)) { PlaytimePainter.Open_Email(); } #endif return(changed); }
public static bool IsBigRenderTexturePair(this Texture tex) { return((tex != null) && PainterCamera.GotBuffers() && ((tex == PainterCamera.Inst.BigRT_pair[0]))); }