スタンプシールを作りました。
描いたストロークをスタンプのように再利用できるシールを作りました。
コピペシールとも言えなくもない。
ダウンロード
使い方
スタンプにしたい絵などを描きます。
(もっとかわいい猫を描いてください)
ページ内のストロークデータがシールのストロークになります。
(本当はストロークの位置を変えずに、シールの位置を合わせるように移動したかったけど、
onattachでシールの位置を移動しても描画更新されなくておかしくなるので断念しました。)
シールのサイズはストロークの大きさにフィットするようにしています。
実行するとシールの位置にストロークのデータが書き込まれます。
今後
12月にUEIさんがシールアップロード機能を追加してくれる予定なので(つ、つくってるよね?)
enchantMOONユーザでいろんなスタンプの共有ができるといいなー
背景ブロックはじめました
まず始めに背景ブロックを使えるようにしたMOONBlockを置いておきます。
MOONBlockのアップデートと同じで上書きするだけでOKです。
(ご利用は自己責任でお願いします)
MOONBlock-v0.3.3-BGBlock.zip
MOONBlockのソースを眺めていると、こんなのを見つけました。
MOONBlock/js/puppet.blocks.block.enchant.js
enchant.ENV.BG_IMAGE_DICTIONARY = pairsToOption([ [ 'blocks.bgImages.default', null ], [ 'blocks.bgImages.beach', 'beach.png' ], [ 'blocks.bgImages.desert', 'desert.png' ], [ 'blocks.bgImages.sky', 'sky.png' ], [ 'blocks.bgImages.hollywood', 'hollywood.png' ], [ 'blocks.bgImages.eclipse', 'eclipse.png' ], [ 'blocks.bgImages.space', 'spacebg.png' ], [ 'blocks.bgImages.table', 'table.png' ], [ 'blocks.bgImages.rpg', 'rpg.png' ], [ 'blocks.bgImages.race', 'race.png' ], [ 'blocks.bgImages.black', 'black.png' ], [ 'blocks.bgImages.blockg', 'blockg.png' ], [ 'blocks.bgImages.actiong', 'actiong.png' ] ]); enchant.block.blocks.game.BackgroundBlock = enchant.Class.create(enchant.block.Block, { initialize: function() { enchant.block.Block.call(this, '#ffcc33'); this.addLabel(RES('blocks.BackgroundBlock.name')); this.addSelectForm(enchant.ENV.BG_IMAGE_DICTIONARY, 'bgsrc'); this.script = 'enchant.puppet.Theatre.changeScreen("<% bgsrc %>");'; } });
これは明らかに背景ブロックですね〜
せっかくなんで使えるようにしてあげましょう。
"BackgroundBlock"でgrepすると背景ブロックを抑止している部分を見つけました。
MOONBlock/main.js
var akbar = new ActionKitBar(); akbar.box[RES('blocks.categories.game')].removeItem('BackgroundBlock'); // ここで背景ブロックが消されています akbar.box.JavaScript.removeItem('BlackBlock'); // こっちはブラックボックスブロックを消しているようです akbar.x = 8; akbar.y = uiMargin; manager.registerDragTarget(akbar); akbar.addEventListener('blockreceived', function(e) { var b = e.block; if (isAllowedRemoving(b)) { blockGroup.removeChild(e.block); } }); scene.addChild(akbar);
ActionKitBarというのがMOONBlock上部に表示されるブロックの入っている箱達のようです。
こいつの生成直後にremoveItemされちゃってるので、
ここをコメントアウトしてやれば背景ブロックが出るはず。
はい。背景ブロックは出ましたが、
ブロックがつんつるてんでどこにもハマりません。。。
実行してみても案の定何も起きません。
この子大丈夫かしら。
どうしようもないので、ほかのブロックを参考にしてみることに。
最近追加されたサウンドブロックを見てみます。
enchant.block.blocks.game.SEBlock = enchant.Class.create(enchant.block.Block, { initialize: function() { enchant.block.Block.call(this, '#3399cc'); this.setConnectTarget('evalable'); // こいつ怪しい this.addLabel(RES('blocks.SEBlock.name')); this.addSelectForm(enchant.ENV.SE_DICTIONARY, 'sesrc'); this._playing = null; this.addLabel('\u25B6') .style({ font: '32px selif', color: '#00ff00' }) .on(enchant.Event.TOUCH_END, function() { this.parentNode.preview(); }); this.iteratize(); // こいつも怪しい this.script = 'enchant.Core.instance.assets["<% sesrc %>"].clone().play();'; }, preview: function() { if (this._playing) { this._playing.stop(); } this._playing = enchant.Core.instance.assets[this.getSentence('sesrc')].clone(); this._playing.play(); } });
うーん以下の二つが怪しいですね。
this.setConnectTarget('evalable');
this.iteratize();
調べてみると、どちらもブロック基本クラスのfunctionのようです。
MOONBlock/js/block.enchant.js
enchant.block.Block = enchant.Class.create(enchant.block.Draggable, { ... /** [lang:ja] * ブロックが接続できるReceptorのタイプを設定する. * @see enchant.block.Connector * @see enchant.block.Receptor * @see enchant.block.MultipleReceptor * @param {String|Array.<String>} type 接続できるようにしたいReceptorのtype. [/lang] */ setConnectTarget: function(type) { if (this.connectable) { this.connector.type = type; } else { this.connector = new enchant.block.Connector(type); this.connector.parentNode = this; this.connectable = true; } }, ... /** [lang:ja] * ブロックを直列に接続できるように設定する. * {@link enchant.block.Block#setConnectTarget}で設定したタイプと同じタイプのブロックが下に接続できるようになる. * connectTargetを設定していない場合は, 引数にtypeを指定する必要がある. * ブロックに特別なReceptorを設定するため, iteratizeの呼び出し後にレイアウトを追加することはできない. * @param {String} [type] タイプ. [/lang] */ iteratize: function(type) { if (this.connectable) { if (this._lastLine.length) { this.addBR(); } var receptor = new enchant.block.Receptor(this.connector.type, this); var C_B_OFST = getBGAsset(this.edgeColor, 'C_B').height / 2; receptor.width = receptor._defaultWidth = C_B_OFST; receptor.height = receptor._defaultHeight = C_B_OFST; this._nextReceptor = receptor; this._addElement(receptor); this.iteratable = true; } else if (type) { this.setConnectTarget(type); this.iteratize(); } else { throw new Error('Block.iteratize() should call after set connect target'); } }, ...
setConnectTargetはブロックのコネクタタイプを設定するfunctionらしい。
ブロックにはコネクタ(挿す側)とレセプタ(挿される側)があり、
このタイプが一致しないとブロック同士が接続できないようです。
とりあえずサウンドブロックと同じ感じで使えればいいので、setConnectTargetには'evalable'を指定しておきます。
タイプは今のところ7つあるようですが、まぁ詳しくは追々調べましょう。
evalable:評価?処理? expression:式 number:数値 string:文字列 behavior:ビヘイビア(振る舞い) property:変数 startPin:開始位置
iteratizeはコメントの通り、同じタイプのブロックが下に接続できるようになります。
これもサウンドブロックと同様に呼んでおきましょう。
こいつは呼び出し順に制約があるようなのでscriptの前で呼ぶようにしておきます。
はい、こんな感じになりました。
MOONBlock/js/puppet.blocks.block.enchant.js
enchant.block.blocks.game.BackgroundBlock = enchant.Class.create(enchant.block.Block, { initialize: function() { enchant.block.Block.call(this, '#ffcc33'); this.setConnectTarget('evalable'); // 追加 this.addLabel(RES('blocks.BackgroundBlock.name')); this.addSelectForm(enchant.ENV.BG_IMAGE_DICTIONARY, 'bgsrc'); this.iteratize(); // 追加 this.script = 'enchant.puppet.Theatre.changeScreen("<% bgsrc %>");'; } });
MOONBlockで開くと、サウンドブロックと同じ形になっているのが確認できました。
さて、使い方ですが、こんな風にシールブロックのタップされたときに繋げても、
何故か起動時に一瞬表示されるだけでまともに動きません。(なんでだろ。。。)
以下のように、0秒後に実行や、スコアボードが画面に現れたタイミングに設定してやるとちゃんと動きました。
少し使い方が微妙な感じがしますが、使えなくはないのでOKでしょう!
Javaメモ lib/ext
久しぶりにJavaに触れてすっかり忘れてたことをメモ。
lib/extにjarを置いておくと実行時にパスを指定しなくてもいい。
lib/extの場所がわからない場合は以下を実行すればOK。
public class ExtensionPath { public static void main (String[] args) { System.out.println(System.getProperty("java.ext.dirs")); } }拡張フォルダのパスを取得する:JavaTips 〜JSP/サーブレット編 - @IT
XML::FeedPPで更新日付が取得できない
PerlでXML::FeedPPってモジュール使って、RSSを取得するプログラム作ってたんだけど、あるサイトだけ更新日付が取得できない。
更新日付入ってないのかな?と思ってとりあえずRSSのソースを見てみる。
<item> <title> たいとるだよ!</title> <link> http://hogehoge.com/ </link> <dc:date> 2010-10-10T12:34:56+09:00</dc:date> <content:encoded><![CDATA[ ほげほげー ]]></content:encoded> </item>
なんか変な所に改行入ってるけど
改行のせいかなーと思って
修正する為にデバッガで追っかけてみたらこのサブルーチンが原因だった。
XML::FeedPP::Util::get_w3cdtf
sub get_w3cdtf { my $date = shift; return unless defined $date; if ( $date =~ /^\d+$/s ) { return &epoch_to_w3cdtf($date); } elsif ( $date =~ $rfc1123_regexp ) { return &rfc1123_to_w3cdtf($date); } elsif ( $date =~ $w3cdtf_regexp ) { return $date; } undef; } #$rfc1123_regexpと$w3cdtf_regexpの定義 my $rfc1123_regexp = qr{ ^(?:[A-Za-z]+,\s*)? (\d+)\s+ ([A-Za-z]+)\s+ (\d+)\s+ (\d+):(\d+)(?::(\d+)(?:\.\d*)?)?\s* ([\+\-]\d+:?\d{2} | [ECMP][DS]T )? }xi; my $w3cdtf_regexp = qr{ ^(\d+)-(\d+)-(\d+) (?:T(\d+):(\d+)(?::(\d+)(?:\.\d*)?\:?)?\s* ([\+\-]\d+:?\d{2})?|$) }x;
日付のフォーマットを判定するところで、日付の前後に改行とかスペースが含まれていることが想定されて無いみたい。
なので、判定する前に日付の前後の改行と空白文字を取り除いてやったらうまく行った!
sub get_w3cdtf { my $date = shift; return unless defined $date; $date =~ s/(^[\s\R]*)|([\s\R]*$)//g; # 前後の改行と空白文字を取り除く if ( $date =~ /^\d+$/s ) { return &epoch_to_w3cdtf($date); } elsif ( $date =~ $rfc1123_regexp ) { return &rfc1123_to_w3cdtf($date); } elsif ( $date =~ $w3cdtf_regexp ) { return $date; } undef; }
SendmailでGmailに転送
実験用のLinux機が欲しい!ということでここを参考にサーバを作り始める。
が、しかし、しょっぱなroot宛のメールを転送する設定でつまずく・・・
書いてあるとおりにやったのに!大人はうそつきだ!
結局1日がかりでごにょごにょしてました。
参考にしたのはこのへん。
OP25B(Outbound Port 25 Blocking)対策 - CentOSで自宅サーバー構築
sendmailでGmailへ転送すること - ワインのばか
http://james-lloyd.com/getting-sendmail-use-gmail-as-a-relay-2/
Configuring Sendmail to relay through Gmail SMTP | AppGirlAppGirl
途中経過書いても仕方ないので最終的にやったことだけ書く。
まず環境
CentOS 5.4
Sendmail 8.13.8-2.el5
んで設定
まず /etc/mail/sendmail.mc の編集
dnl define(`SMART_HOST', `smtp.your.provider')dnl の次の行に以下を追加。
define(`SMART_HOST', `smtp.gmail.com')dnl
define(`ESMTP_MAILER_ARGS', `TCP $h 587')
define(`RELAY_MAILER_ARGS', `TCP $h 587')
FEATURE(authinfo, DATABASE_MAP_TYPE` -o 'MAIL_SETTINGS_DIR`authinfo')
define(`confAUTH_MECHANISMS', `EXTERNAL GSSAPI DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')
TRUST_AUTH_MECH(`EXTERNAL DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')
そんで
dnl DAEMON_OPTIONS(`Port=submission, Name=MSA, M=Ea')dnl のコメントを外す。
DAEMON_OPTIONS(`Port=submission, Name=MSA, M=Ea')dnl
最後に
dnl FEATURE(masquerade_envelope)dnlの行の次に以下を追加。
FEATURE(masquerade_envelope)dnl
FEATURE(genericstable, DATABASE_MAP_TYPE` -o 'MAIL_SETTINGS_DIR`genericstable')
GENERICS_DOMAIN_FILE(MAIL_SETTINGS_DIR`genericsdomain')
FEATURE(`generics_entire_domain')
次はauthinfoファイルを作る。
中身はこんな感じ。
makemap hash /etc/mail/authinfo.db < /etc/mail/authinfo
次はgenericsdomainファイルを作る。
これでOK。次はgenericstableファイルを作る。
でgenericstable.dbを作る。makemap hash /etc/mail/genericstable.db < /etc/mail/genericstable
hoge@gmail.comは送信に使うgmailアカウントなので各自置き換えること。
sendmailの設定はこれで終わりなので設定を反映させる。
/etc/rc.d/init.d/sendmail reload
最後に送信先を設定する。
/etc/aliasesのroot:なんたらかんたら って行を書き換える。
デフォルトではコメントになってた気がする。
#root: michael
root: huga@gmail.com
これでroot宛のメールはhuga@gmail.comに送られる。
newaliases
echo test|mail root
name属性の廃止
XHTMLを解説しているページの多くで、
XHTML1.0からはname属性は廃止です。
name属性はid属性にかえましょう。
的な事が書いてあるんで、すべてのname属性が廃止なんだと思ってた。
でも、あれ?じゃあチェックボックスやラジオボタンのグループ化ってどうやってやんの?
と思って調べていたら、name属性の廃止は一部の要素についてのみということが判明。
紛らわしい書き方なんで、他にも誤解してる人いっぱい居そう・・・
え?プロにとっては常識?そうですか・・・
以下にname属性を使える要素についてまとめてみました。
本やサイトなどから引っ張ってきたのでなく、きちんとDTDを読んだので正確だと思います。
○:name属性使用可
×:name属性廃止
‐:要素自体が廃止
要素 | XHTML1.0 | XHTML1.1 | ||
---|---|---|---|---|
frameset | transitional | strict | ||
a | ○ | ○ | ○ | × |
map | ○ | ○ | ○ | × |
img | ○ | ○ | × | × |
form | ○ | ○ | × | × |
iframe | ○ | ○ | - | - |
applet | ○ | ○ | - | - |
frame | ○ | - | - | - |
meta | ○ | ○ | ○ | ○ |
object | ○ | ○ | ○ | ○ |
param | ○ | ○ | ○ | ○ |
input | ○ | ○ | ○ | ○ |
select | ○ | ○ | ○ | ○ |
textarea | ○ | ○ | ○ | ○ |
button | ○ | ○ | ○ | ○ |