python桌面宠物_【Unity/开源】八重樱桌宠(三):Python自动更新、修复描边

接下来就到了喜闻乐见的PY环节:

defget_html(url):try:headers = { "Host": "github.com","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"}r = requests.get(url, timeout= 15, headers=headers)r.raise_for_status# print(r.status_code)# 这里我们知道编码是utf-8,爬其他的页面时建议使用:# r.endcodding = r.apparent_endcondingr.encoding = 'utf-8'returnr.textexcept:returnNone

defget_GithubData(url):

posts = {}html = get_html(url)ifhtml == None:print( '网络错误,请确保能够访问GitHub!n')returnNone

soup = BeautifulSoup(html, 'lxml')newUrl = ''try:div = soup.find('div', class_= 'd-flex flex-items-center')string = div.find( 'a')[ 'data-hydro-click'] + ''newUrl = (json.loads(string))[ 'payload'][ 'originating_url']except:print( '获取重定向网址失败!n')returnNone# 开始重定向到新网址print( '重定向到:'+ newUrl + 'n')html = get_html(newUrl)ifhtml == None:print( '网络错误,请确保能够访问GitHub!n')returnNonesoup = BeautifulSoup(html, 'lxml')

try:release = soup.find( 'div', class_= 'border-top')posts[ 'ver'] = release.find('a', class_= 'muted-link css-truncate')[ 'title']print( '最新版本:'+ posts[ 'ver'])

posts[ 'log'] = release.find('div', class_= 'markdown-body').find( 'p').textprint( '更新日志:'+ posts[ 'log'])

posts[ 'time'] = release.find( 'relative-time').textprint( '更新时间:'+ posts[ 'time'])

posts[ 'URL'] = 'https://github.com/'+ release.find('a', class_= 'd-flex flex-items-center min-width-0')[ 'href']print( '下载地址:'+ posts[ 'URL'] + 'n')print( '若速度过慢可手动前往码云下载:nthttps://gitee.com/JasonMa233/Sakura_DesktopMascot/releasesn')except:print( 'Github数据爬取失败!n')returnNonereturnposts

# 下面的go是自定义的回调函数,每次调用它都会打印出当前下载进度defgo(blocknum, blocksize, totalsize):iftotalsize > 0:percent = blocknum*blocksize/totalsizeifpercent > 1:percent = 1else:percent = totalsize# blocknum是数据块的数量,我只下载一个压缩包,所以它等于1;blocksize是已经下载的文件大小,totalsize是文件总大小。print( 'r已下载:{:.2%} ({:.3f}/{:.1f}MB)'.format(percent, blocknum * blocksize / 1000000, totalsize / 1000000), end= '')

out = { 0: '>按回车退出按回车重试按回车开始更新

defOutput(code):input(out.get(code, '无此消息!n'))

# 终端命令:PyInstaller -F Update.py 打包py为exeif__name__ == "__main__":print( 't-==八重樱桌宠==-nn')exePath, ver = 'Sakura_DesktopMascot.exe', '1'iflen(sys.argv) > 1:os.chdir(sys.argv[ 1])ifos.path.exists( 'Ver.data'):f = open( 'Ver.data')ver = f.readlineexePath = f.readlinef.closeelse:print( '请先运行桌宠!n')ifver != '1':print( '当前版本:'+ ver + 'n')else:print( '当前版本:未知 请尝试使用桌宠程序检查更新,或选择继续更新!n')

whileTrue:print( '检查更新中……nn')githubData = get_GithubData('https://github.com/Jason-Ma-233/Sakura_DesktopMascot/releases/latest')ifgithubData != None:# 若拿到更新数据则检查是否需要更新iffloat(ver) < float(githubData[ 'ver']):Output( 2)# 下载压缩包tempPath = 'temp'ifnotos.path.exists(tempPath):os.mkdir(tempPath)tempFilePath = 'temp/Update.zip'urlretrieve(githubData[ 'URL'], tempFilePath, go)# 关闭程序print( '关闭程序并解压中……n')os.system( "taskkill /F /IM "+ exePath)# 解压覆盖f = zipfile.ZipFile(tempFilePath, 'r')forfile inf.namelist:iffile != 'Update.exe':f.extract(file, r'.')# 删除temp文件夹f.closeos.remove(tempFilePath)os.rmdir(tempPath)# 重启程序os.startfile(exePath)print( '更新完成!nn3秒后自动关闭……n')time.sleep( 3)breakelse:print( '无需更新!nn3秒后自动关闭……n')time.sleep( 3)breakelse:Output( 1)continue

开头先读取运行参数和前面的版本文件,紧接着一个检查更新循环,首先是一个爬虫,爬取Github上的更新信息,虽然Github速度比起码云可能会慢很多,但是不用登录。有关爬虫的细节我个人也是现学现卖,参考以下文章:

看完贴吧的爬取过程就可以写自己的爬虫了, github.com/.../.../rele这个链接中带有最新发布版明文链接,重定向之后获取最新版本的信息并返回。

接下来无非就是下载、解压覆盖、删除临时文件、重启程序,下载urlretrieve一行搞定,解压用zipfile轻松完成,偶尔写个python就是这么令人神清气爽,相对于C艹艹优雅得想要怒吼一声。

最后检查无误使用PyInstaller执行命令PyInstaller -F Update.py将当前脚本打包为EXE,放入桌宠包体内,自动更新大功告成。

0.1 修复描边

之前提到过桌宠的描边缺失:

显而易见是抠图的Shader将描边抠掉了:

得知描边没有被写入深度图,查手册得知需要ShadowCaster Pass来写入深度图,而自带的ShadowCaster并没有顶点偏移,所以描边被抠掉了。于是自定义一个带顶点偏移的ShadowCaster放前两个Pass后面:

MyShadow.cginc:

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

#ifndef UNITY_STANDARD_SHADOW_INCLUDED# defineUNITY_STANDARD_SHADOW_INCLUDED

// NOTE:had to split shadow functions into separate file,// otherwise compiler gives trouble with LIGHTING_COORDS macro (in UnityStandardCore.cginc)

#include "UnityCG.cginc"#include "UnityShaderVariables.cginc"#include "UnityStandardConfig.cginc"#include "UnityStandardUtils.cginc"

# if(defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON)) && defined(UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS)# defineUNITY_STANDARD_USE_DITHER_MASK 1# endif

// Need to output UVs in shadow caster, since we need to sample texture and do clip/dithering based on it# ifdefined(_ALPHATEST_ON) || defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON)# defineUNITY_STANDARD_USE_SHADOW_UVS 1# endif

// Has a non-empty shadow caster output struct (it's an error to have empty structs on some platforms...)# if!defined(V2F_SHADOW_CASTER_NOPOS_IS_EMPTY) || defined(UNITY_STANDARD_USE_SHADOW_UVS)# defineUNITY_STANDARD_USE_SHADOW_OUTPUT_STRUCT 1# endif

#ifdef UNITY_STEREO_INSTANCING_ENABLED# defineUNITY_STANDARD_USE_STEREO_SHADOW_OUTPUT_STRUCT 1# endif

half4 _Color;half _Cutoff;sampler2D _MainTex;float4 _MainTex_ST;#ifdef UNITY_STANDARD_USE_DITHER_MASKsampler3D _DitherMaskLOD;# endif

// Handle PremultipliedAlpha from Fade or Transparent shading modehalf4 _SpecColor;half _Metallic;#ifdef _SPECGLOSSMAPsampler2D _SpecGlossMap;# endif#ifdef _METALLICGLOSSMAPsampler2D _MetallicGlossMap;# endif

# ifdefined(UNITY_STANDARD_USE_SHADOW_UVS) && defined(_PARALLAXMAP)sampler2D _ParallaxMap;half _Parallax;# endif

half MetallicSetup_ShadowGetOneMinusReflectivity( half2 uv){half metallicity = _Metallic;#ifdef _METALLICGLOSSMAPmetallicity = tex2D(_MetallicGlossMap, uv).r;# endifreturnOneMinusReflectivityFromMetallic(metallicity);}

half RoughnessSetup_ShadowGetOneMinusReflectivity( half2 uv){half metallicity = _Metallic;#ifdef _METALLICGLOSSMAPmetallicity = tex2D(_MetallicGlossMap, uv).r;# endifreturnOneMinusReflectivityFromMetallic(metallicity);}

half SpecularSetup_ShadowGetOneMinusReflectivity( half2 uv){half3 specColor = _SpecColor.rgb;#ifdef _SPECGLOSSMAPspecColor = tex2D(_SpecGlossMap, uv).rgb;# endifreturn( 1- SpecularStrength(specColor));}

// SHADOW_ONEMINUSREFLECTIVITY: workaround to get one minus reflectivity based on UNITY_SETUP_BRDF_INPUT# defineSHADOW_JOIN2(a, b) a##b# defineSHADOW_JOIN(a, b) SHADOW_JOIN2(a,b)# defineSHADOW_ONEMINUSREFLECTIVITY SHADOW_JOIN(UNITY_SETUP_BRDF_INPUT, _ShadowGetOneMinusReflectivity)

structVertexInput{float4 vertex : POSITION;float3 normal : NORMAL;float2 uv0 : TEXCOORD0;# ifdefined(UNITY_STANDARD_USE_SHADOW_UVS) && defined(_PARALLAXMAP)half4 tangent : TANGENT;# endifUNITY_VERTEX_INPUT_INSTANCE_ID};

#ifdef UNITY_STANDARD_USE_SHADOW_OUTPUT_STRUCTstructVertexOutputShadowCaster{V2F_SHADOW_CASTER_NOPOS# ifdefined(UNITY_STANDARD_USE_SHADOW_UVS)float2 tex : TEXCOORD1;

# ifdefined(_PARALLAXMAP)half3 viewDirForParallax : TEXCOORD2;# endif# endif};# endif

#ifdef UNITY_STANDARD_USE_STEREO_SHADOW_OUTPUT_STRUCTstructVertexOutputStereoShadowCaster{UNITY_VERTEX_OUTPUT_STEREO};# endif

float_Outline_Width;sampler2D _ColorMap;

voidvertShadowCaster( VertexInput v, outfloat4 opos : SV_POSITION#ifdef UNITY_STANDARD_USE_SHADOW_OUTPUT_STRUCT, outVertexOutputShadowCaster o#endif#ifdef UNITY_STANDARD_USE_STEREO_SHADOW_OUTPUT_STRUCT, outVertexOutputStereoShadowCaster os#endif){UNITY_SETUP_INSTANCE_ID(v);#ifdef UNITY_STANDARD_USE_STEREO_SHADOW_OUTPUT_STRUCTUNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(os);# endif

float4 _Outline_Sampler_var = tex2Dlod(_ColorMap, float4(v.uv0, 0.0, 0));floatSet_Outline_Width = _Outline_Width * 0.001* _Outline_Sampler_var.a;v.vertex.xyz += v.normal.xyz * Set_Outline_Width;

TRANSFER_SHADOW_CASTER_NOPOS(o,opos)

# ifdefined(UNITY_STANDARD_USE_SHADOW_UVS)o.tex = TRANSFORM_TEX(v.uv0, _MainTex);

#ifdef _PARALLAXMAPTANGENT_SPACE_ROTATION;o.viewDirForParallax = mul (rotation, ObjSpaceViewDir(v.vertex));# endif# endif

// float4 _ClipCameraPos = mul(UNITY_MATRIX_VP, float4(_WorldSpaceCameraPos.xyz, 1));// v.vertex.z += 1 * _ClipCameraPos.z;}

half4 fragShadowCaster( UNITY_POSITION(vpos)#ifdef UNITY_STANDARD_USE_SHADOW_OUTPUT_STRUCT, VertexOutputShadowCaster i#endif) : SV_Target{# ifdefined(UNITY_STANDARD_USE_SHADOW_UVS)# ifdefined(_PARALLAXMAP) && (SHADER_TARGET >= 30)half3 viewDirForParallax = normalize(i.viewDirForParallax);fixedh = tex2D (_ParallaxMap, i.tex.xy).g;half2 offset = ParallaxOffset1Step (h, _Parallax, viewDirForParallax);i.tex.xy += offset;# endif

# ifdefined(_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A)half alpha = _Color.a;# elsehalf alpha = tex2D(_MainTex, i.tex.xy).a * _Color.a;# endif# ifdefined(_ALPHATEST_ON)clip (alpha - _Cutoff);# endif# ifdefined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON)# ifdefined(_ALPHAPREMULTIPLY_ON)half outModifiedAlpha;PreMultiplyAlpha(half3( 0, 0, 0), alpha, SHADOW_ONEMINUSREFLECTIVITY(i.tex), outModifiedAlpha);alpha = outModifiedAlpha;# endif# ifdefined(UNITY_STANDARD_USE_DITHER_MASK)// Use dither mask for alpha blended shadows, based on pixel position xy// and alpha level. Our dither texture is 4x4x16.#ifdef LOD_FADE_CROSSFADE# define_LOD_FADE_ON_ALPHAalpha *= unity_LODFade.y;# endifhalf alphaRef = tex3D(_DitherMaskLOD, float3(vpos.xy* 0.25,alpha* 0.9375)).a;clip (alphaRef - 0.01);# elseclip (alpha - _Cutoff);# endif# endif# endif// # ifdefined(UNITY_STANDARD_USE_SHADOW_UVS)

#ifdef LOD_FADE_CROSSFADE#ifdef _LOD_FADE_ON_ALPHA# undef_LOD_FADE_ON_ALPHA# elseUnityApplyDitherCrossFade(vpos.xy);# endif# endif

SHADOW_CASTER_FRAGMENT(i)// return 0;}

# endif// UNITY_STANDARD_SHADOW_INCLUDED

拿内置ShadowCaster直接改,下面是改动部分:

float4 _Outline_Sampler_var = tex2Dlod(_ColorMap, float4(v.uv0, 0.0, 0));floatSet_Outline_Width = _Outline_Width * 0.001* _Outline_Sampler_var.a;v.vertex.xyz += v.normal.xyz * Set_Outline_Width;

TRANSFER_SHADOW_CASTER_NOPOS(o,opos)

......}

这样一来问题得以解决,由于有描边存在,锯齿也稍微改善了一些。

0.2 后续

紧接着要做的是表情系统,看上去不难,不就UV动画吗?然而真到自己要实现了有点懵,前两天表情系统写道一半结果Animation没法录制脚本中的参数,之后得尝试用材质球CustomEditor去做表情系统,有经验的大佬欢迎留言。

来源:知乎专栏-Unity|Graphics&Waifu

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值