Live 2D

经过一天的摸鱼

我看了好多关于Live2D官方文档,和官方帮助,算是把我落下的内容恶补了一下。

我明白Live2D在2.x版本和3.x-4.x版本之间做了架构性的改动,导致SDK4.x只向下兼容到3.x

Live2D 的2.x可以生成moc文件,而3.0以上版本可以生成moc或者moc3文件,切此文件不可编译(不能恢复成工程文件)

Live2DViewerEX同样做了不可逆操作,将lpk进行了加密操作,但是wpk可以打开,不过其实就是打包的lpk文件而已。

那么我还是继续去了解一下具体的情况,主要是版权的问题很麻烦,关于加载3.0以上版本的SDK已经准备好了,需要进行一些研究才可以使用。

先到这…

Live 2D

看板娘更新啦

更新到了1.6版本,感觉更新有点频繁,虽然使用者不多,但是频繁更新也挺招人烦的,所以我决定更新频率改为每周4进行一次(修复严重BUG除外)

本次更新主要是受到wordpress.org中Support问题提交的灵感,有一说一,我对原本的配色也不是很满意,因为我在应用【主题】的时候发现【Iceable Media】的酷黑很帅,但是我用了看板娘以后发现看板娘的字体刺眼…我瞎了。

所以我昨天正好没啥事做,就在上班摸鱼的过程中更新了看板娘的功能,在阅读过去的代码的时候,发现了不少冗余,所以一并进行了更新。

下一个版本(1.6.5)我会改变【大小设置】的方式,我现在没有想明白“同比例缩放”在后台设置中如何实现。不过得益于WordPress的H5,我可以使用type="range"来进行尺寸的变更,避免用户手填px写错。

那么今天摸鱼开始了!

闲聊

给MI6X MIKU ROOT

好久没用这个手机了,要是说起来,我买回来的时候就没怎么折腾它,卖了IPHONE7 等价换初音这种事情,真的划算吗?

这次更换可Root的开发版,其实是为了可以进行Android Auto的研究,因为在网上看了一下,Android Auto限制非常多,和Carplay一样,你又没有Carplay那么多软件支持,死撑什么呢,也不知道,不过有一说一,国外支持Android Auto的软件其实挺多的,但是用得上不?

为啥折腾Android Auto ,其实要从上个月我自己徒手装车机开始说起

这辆凯迪拉克ATSL被我折腾的够呛啦~

不愧是痛车! 但是装完了原厂车机,又没有Carplay怎么搞呢…

来Android Auto吧!

Android Auto主要需要一个软件进行sqlite3库的改写,我看YouTube上的教程大部分人推荐
AA Phenotype Patcher
,我下载了以后看了一下,这个软件可以改写com.google.android.gms.car的信息

--  Apps which will be added to whitelist: --
  - 虾米音乐 (fm.xiami.main)
  - AA Mirror (com.github.slashmax.aamirror)
  - 高德地图 (com.autonavi.minimap)

--  chmod 775 sqlite3  --
 OutputStream:
  chmod 775 /data/user/0/pl.eselter.aaphenotypepatcher/sqlite3
--  end chmod 775 sqlite3  --

-- Drop Triggers  --
 OutputStream:
  /data/user/0/pl.eselter.aaphenotypepatcher/sqlite3 /data/data/com.google.android.gms/databases/phenotype.db 'DROP TRIGGER after_delete;'

--  DELETE old Flags  --
 OutputStream:
  /data/user/0/pl.eselter.aaphenotypepatcher/sqlite3 /data/data/com.google.android.gms/databases/phenotype.db 'DELETE FROM Flags WHERE name="app_white_list";'

--  run SQL method #1  --
 OutputStream:
  /data/user/0/pl.eselter.aaphenotypepatcher/sqlite3 /data/data/com.google.android.gms/databases/phenotype.db 'INSERT OR REPLACE INTO Flags (packageName, version, flagType, partitionId, user, name, stringVal, committed) VALUES ("com.google.android.gms.car#car", 234, 0, 0, "", "app_white_list", "fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap",1);
  INSERT OR REPLACE INTO Flags (packageName, version, flagType, partitionId, user, name, stringVal, committed) VALUES ("com.google.android.gms.car#car", 230, 0, 0, "", "app_white_list", "fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap",1);
  INSERT OR REPLACE INTO Flags (packageName, version, flagType, partitionId, user, name, stringVal, committed) VALUES ("com.google.android.gms.car", 234, 0, 0, "", "app_white_list", "fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap",1);
  INSERT OR REPLACE INTO Flags (packageName, version, flagType, partitionId, user, name, stringVal, committed) VALUES ("com.google.android.gms.car", 230, 0, 0, "", "app_white_list", "fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap",1);
  INSERT OR REPLACE INTO Flags (packageName, version, flagType, partitionId, user, name, stringVal, committed) VALUES ("com.google.android.gms.car#car_setup", 234, 0, 0, "", "app_white_list", "fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap",1);
  INSERT OR REPLACE INTO Flags (packageName, version, flagType, partitionId, user, name, stringVal, committed) VALUES ("com.google.android.gms.car#car_setup", 230, 0, 0, "", "app_white_list", "fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap",1);
  INSERT OR REPLACE INTO Flags (packageName, version, flagType, partitionId, user, name, stringVal, committed) VALUES ("com.google.android.gms.car#car", (SELECT version FROM Packages WHERE packageName="com.google.android.gms.car#car"), 0, 0, "", "app_white_list", "fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap",1);
  INSERT OR REPLACE INTO Flags (packageName, version, flagType, partitionId, user, name, stringVal, committed) VALUES ("com.google.android.gms.car", (SELECT version FROM Packages WHERE packageName="com.google.android.gms.car"), 0, 0, "", "app_white_list", "fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap",1);
  INSERT OR REPLACE INTO Flags (packageName, version, flagType, partitionId, user, name, stringVal, committed) VALUES ("com.google.android.gms.car#car_setup", (SELECT version FROM Packages WHERE packageName="com.google.android.gms.car#car"), 0, 0, "", "app_white_list", "fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap",1);'
 OutputStream:
  /data/user/0/pl.eselter.aaphenotypepatcher/sqlite3 /data/data/com.google.android.gms/databases/phenotype.db 'CREATE TRIGGER after_delete AFTER DELETE
  ON Flags
  BEGIN
  INSERT OR REPLACE INTO Flags (packageName, version, flagType, partitionId, user, name, stringVal, committed) VALUES ("com.google.android.gms.car#car", (SELECT version FROM Packages WHERE packageName="com.google.android.gms.car#car"), 0, 0, "", "app_white_list", "fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap",1);
  INSERT OR REPLACE INTO Flags (packageName, version, flagType, partitionId, user, name, stringVal, committed) VALUES ("com.google.android.gms.car#car", 230, 0, 0, "", "app_white_list", "fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap",1);
  INSERT OR REPLACE INTO Flags (packageName, version, flagType, partitionId, user, name, stringVal, committed) VALUES ("com.google.android.gms.car#car", 234, 0, 0, "", "app_white_list", "fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap",1);
  INSERT OR REPLACE INTO Flags (packageName, version, flagType, partitionId, user, name, stringVal, committed) VALUES ("com.google.android.gms.car", (SELECT version FROM Packages WHERE packageName="com.google.android.gms.car"), 0, 0, "", "app_white_list", "fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap",1);
  INSERT OR REPLACE INTO Flags (packageName, version, flagType, partitionId, user, name, stringVal, committed) VALUES ("com.google.android.gms.car", 230, 0, 0, "", "app_white_list", "fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap",1);
  INSERT OR REPLACE INTO Flags (packageName, version, flagType, partitionId, user, name, stringVal, committed) VALUES ("com.google.android.gms.car", 234, 0, 0, "", "app_white_list", "fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap",1);
  INSERT OR REPLACE INTO Flags (packageName, version, flagType, partitionId, user, name, stringVal, committed) VALUES ("com.google.android.gms.car#car_setup", (SELECT version FROM Packages WHERE packageName="com.google.android.gms.car#car"), 0, 0, "", "app_white_list", "fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap",1);
  INSERT OR REPLACE INTO Flags (packageName, version, flagType, partitionId, user, name, stringVal, committed) VALUES ("com.google.android.gms.car#car_setup", 230, 0, 0, "", "app_white_list", "fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap",1);
  INSERT OR REPLACE INTO Flags (packageName, version, flagType, partitionId, user, name, stringVal, committed) VALUES ("com.google.android.gms.car#car_setup", 234, 0, 0, "", "app_white_list", "fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap",1);
  END;'
--  end SQL method #1  --

--  Check (1/3)  --
 OutputStream:
  /data/user/0/pl.eselter.aaphenotypepatcher/sqlite3 /data/data/com.google.android.gms/databases/phenotype.db 'SELECT * FROM Flags WHERE name="app_white_list";'
 InputStream:
  com.google.android.gms.car#car_setup|230|0|0||app_white_list||||fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap||1
  com.google.android.gms.car#car_setup|234|0|0||app_white_list||||fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap||1
  com.google.android.gms.car#car|230|0|0||app_white_list||||fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap||1
  com.google.android.gms.car#car|234|0|0||app_white_list||||fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap||1
  com.google.android.gms.car|230|0|0||app_white_list||||fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap||1
  com.google.android.gms.car|234|0|0||app_white_list||||fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap||1
  com.google.android.gms.car|247|0|0||app_white_list||||fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap||1
--  Check (2/3)  --
 OutputStream:
  /data/user/0/pl.eselter.aaphenotypepatcher/sqlite3 /data/data/com.google.android.gms/databases/phenotype.db 'DELETE FROM Flags WHERE name="app_white_list";'
--  Check (3/3)  --
 OutputStream:
  /data/user/0/pl.eselter.aaphenotypepatcher/sqlite3 /data/data/com.google.android.gms/databases/phenotype.db 'SELECT * FROM Flags WHERE name="app_white_list";'
 InputStream:
  com.google.android.gms.car#car_setup|230|0|0||app_white_list||||fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap||1
  com.google.android.gms.car#car_setup|234|0|0||app_white_list||||fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap||1
  com.google.android.gms.car#car|230|0|0||app_white_list||||fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap||1
  com.google.android.gms.car#car|234|0|0||app_white_list||||fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap||1
  com.google.android.gms.car|230|0|0||app_white_list||||fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap||1
  com.google.android.gms.car|234|0|0||app_white_list||||fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap||1
  com.google.android.gms.car|247|0|0||app_white_list||||fm.xiami.main,com.github.slashmax.aamirror,com.autonavi.minimap||1

--  Check seems OK :)  --

通过这种方式可能会让Android Auto应用中增加指定的APP,网上说AA Phenotype Patcher需要配合AAMirror使用,因为比较晚,明天去车上试试,顺便拍几个照片!

Live 2D

Live2D看板娘上线啦

很高兴,插件经过了审核,并可以在wordpress插件库中上线。

可以通过搜索Live 2D、萌等关键词进行搜索和安装。

后期我准备把对话功能加入插件中,主要是和AI对话,目前还在考虑对话样式的问题。

其实我还有考虑如何更容易的制作模型,不知道做一个模型的平台是否靠谱,先研究一下原作者的代码。

Live 2D

看板娘改造完成了

fghrsh.net弄来的看板娘被改造到了WordPress插件中,这中间遇到不少坑。

首先是我不会PHP的问题,大部分都是在网上查的,我一直以为弱类型语言比较随意,其实也是需要进行数据类型的强转的。这个主要是在WordPress的register_setting函数中,有一个sanitize回调函数,这个回调函数主要是获得传值并进行数据清理,在看板娘中有如下代码:

if (!live2d_settings.showToolMenu) $('.waifu-tool').hide();
if (!live2d_settings.canCloseLive2d) $('.waifu-tool .fui-cross').hide();
if (!live2d_settings.canSwitchModel) $('.waifu-tool .fui-eye').hide();
if (!live2d_settings.canSwitchTextures) $('.waifu-tool .fui-user').hide();
if (!live2d_settings.canSwitchHitokoto) $('.waifu-tool .fui-chat').hide();
if (!live2d_settings.canTakeScreenshot) $('.waifu-tool .fui-photo').hide();
if (!live2d_settings.canTurnToHomePage) $('.waifu-tool .fui-home').hide();
if (!live2d_settings.canTurnToAboutPage) $('.waifu-tool .fui-info-circle').hide();

这里的设置接收的是一个Boolean类型,在JSON序列化之后这个对象中的每一个属性都变成了String 类型,无法进行判断。所以还是不能偷懒,最后强制转换为Boolean类型就可以使用了。

之前还想偷懒不进行register_activation_hook钩子的设定,后来发现可能会带来不少麻烦事,所以还是选择在安装插件的时候直接向options表中写入数据,并在register_uninstall_hook卸载插件钩子的时候将增加的字段删除,保证WP的数据库不会保留太多的垃圾数据。

去除了一个鼠标事件.waifu #live2d可以避免鼠标每次经过看板娘的时候他就混乱的说各种话。

因为在界面中动态增加array真的太麻烦了,所以没有做某个事件的多语言随机。

最后,设置图:

闲聊

WordPress插件开发:为add_settings_field 添加多个input

我在做插件的时候,发现有一些数组型的插件设置,想保存到同一个字段中,但是在国内找了一些文章,没有描述如何活用add_settings_field 。

我这次就尝试如何给一个add_settings_field中放置多个input,

add_settings_field(
    'hour_tips', // id
    '每个小时的提示', // title
    array( $this, 'hour_tips_callback' ), // callback
    'live-2d-advanced-admin', // page
    'live_2d_advanced_setting_section' // section
);

在这里,使用hour_tips_callback 作为此控件的回调方法

public function hour_tips_callback() {
    printf(
        '<input class="regular-text" style="width: 100px" type="text" name="live_2d_advanced_option_name[hour_tips][0][0]" id="hour_tips_1" value="%s"> 时 
         <input class="regular-text" type="text" name="live_2d_advanced_option_name[hour_tips][0][1]" id="hour_tips_2" value="%s"><br />',
        isset( $this->live_2d_advanced_options['hour_tips'][0][0] ) ? esc_attr( $this->live_2d_advanced_options['hour_tips'][0][0]) : '',
        isset( $this->live_2d_advanced_options['hour_tips'][0][1] ) ? esc_attr( $this->live_2d_advanced_options['hour_tips'][0][1]) : ''
    );
}

在options名字中:live_2d_advanced_options 作为一个options的字段,可以存储多维数据,我就把此作为Array,保存成了二维数组,我不知道在PHP中应该怎么描述,应为我一直是做.net的开发,对这个只是刚入门,我从数据库观察,其大致原理为:在wp-options这个标中创建一个新行,其名称为live_2d_advanced_option_name,其中存储一个WP定义的数据组,数据组是字符串,可保存普通字符串或者是一个List。

add_settings_field的sanitize过滤器中,需要传递一个不经过过滤的对象:

if ( isset( $input['hour_tips'] ) ) {
    $sanitary_values['hour_tips'] = $input['hour_tips'];
}

这样数据就会被保存至Wp-api中存储至wp-options内。

旅行

今天周末

疫情又来了,趁着疫情还没开始蔓延,我和媳妇赶紧出去逛逛,去了石刻博物馆,后来我想起很早很早以前我来过这里,是参加一个漫展的。

石刻博物馆结束之后,我们就直接去了对面的动物园,旺季门票15元,真的比石刻博物馆的20元门票值多了,好久没来北京动物园了,我上学的时候还来过几次。

Live 2D

把Live 2D看板娘添加到wordpress

今天算是完成了基本设置功能,我把这个功能在版本中列为1.1

如果你看到我的这篇文章,请移步到Github上进行插件下载,安装完成后即可在后台进行基本设置。

高级设置还在制作中,因为刚开始学习PHP相关的内容,本人又是产品经理岗位,可能更新速度并不是很快。

高级设置目前可以进行保存,但是保存的内容是我预设的值,比原作者预设值少一些,主要少在事件消息上。因为原作者使用的是Z-blog,他的选择器不适用于WordPress,如果你知道如何使用选择器,可修改 “src/waifu-options.php” 中的“可循环”,追加内容后,可自己在整个页面的事件中进行定义。