Explore the Snark http://log.moremorefor.net/rss UI Design, Game graphics, Programmingとか. Photoshopとか. http://www.rssboard.org/rss-specification python-feedgen ja Tue, 19 Mar 2024 03:04:49 +0000 「ゲームプログラマになる前に覚えておきたい技術」のサンプルコードをWindows10のVisual Studio Community 2015でビルドする http://log.moremorefor.net/entry/game-programmer-book-build-vs2015 <p><img src="/entry/game-programmer-book-build-vs2015/book.png" alt="book.png" title="None"/> </p> <p><a href="https://www.amazon.co.jp/dp/4798021180" title="None" target="_blank">ゲームプログラマになる前に覚えておきたい技術</a> </p> <p>C++を勉強する題材として読み始めた。が、サンプルコードが動かない(と思う</p> <p>1章は問題なくビルドできるが、GameLibを使うようになる2章からはライブラリをビルドし直さないと動かないっぽい。で、少しハマったが、結果的にこの手順でうまくいった。</p> <p>Windowsでの開発自体が初心者で色々ハマったので、同じように普段Macで開発していてC++をこの本で勉強しようと思っている人の参考になればいいなと思う。</p> <p>基本的にこのブログの手順を参考にさせていただきました。ありがとうございます。</p> <p><a href="http://blog.techlab-xe.net/archives/368" title="None" target="_blank">新 「ゲームプログラマになる前に覚えておきたい技術」 VS2010対応</a> </p> <h3>手順は以下の通り</h3> <ol> <li>サンプルコードをダウンロード</li> <li>環境変数の設定</li> <li>ライブラリのモジュールのビルド</li> <li>ライブラリのビルド</li> <li>サンプルコードの実行</li> </ol> <p>タイトルにも書いたけど環境は、</p> <ul> <li>Windows 10</li> <li>Visual Studio Community 2015</li> </ul> <h2>サンプルコードをダウンロード</h2> <p>まず、 <a href="http://www.shuwasystem.co.jp/support/7980html/2118.html" title="None" target="_blank">ゲームプログラマになる前に覚えておきたい技術|サポート|秀和システム</a> </p> <p>ここからVisual Studio 2012用の<code>GameLib2012.zip</code>をダウンロードする</p> <p>それを適当な場所に解凍する。 このとき、半角スペースや+など特殊な文字が含まれていないディレクトリ以下に解凍すること。 とりあえずCドライブや書籍内に書いてあるようにDドライブ直下などがいいと思う。(自分の場合<code>C++</code>というディレクトリ名以下に解凍していたせいで以下のエラーで失敗していた)</p> <h5>MSB3037 のエラーが出た場合の対処</h5> <p><a href="http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1461877284" title="None" target="_blank">「ゲームプログラマになる前に覚えておきたい技術」のCDについて - Yahoo!知恵袋</a> </p> <h2>環境変数の設定</h2> <p>次に本の指示と同じように環境変数を設定する 「Windows」アイコンを右クリックし、「システム」を開き、「システムの詳細設定」の「環境変数」から設定する。</p> <p>ユーザー環境設定の新規から</p> <ul> <li>変数: <code>GAME_LIB_DIR</code></li> <li>値: <code>先ほど解凍したディレクトリのパス</code> (例)C:\GameLib2012</li> </ul> <p>を設定する。 環境変数の反映のさせ方がわからないのでとりあえずこの時点でPCを再起動した。</p> <h2>ライブラリのモジュールのビルド</h2> <p>次に、 <code>GameLib2012\src\GameLibs\Modules\Modules.sln</code> のソリューションを開く。 このとき、コンパイラとライブラリをアップデートするか訊かれるのでOKにしておく。</p> <ul> <li>メニューの「ビルド &gt; バッチビルド」を選択</li> <li>「全て選択」をクリック</li> <li>「リビルド」を押してリビルドを開始する。</li> </ul> <p>ここでおそらくminとmaxが見つからないエラーが出る。</p> <blockquote> <p>エラー C3861 &#39;max&#39;: 識別子が見つかりませんでした</p> </blockquote> <p>これはalgorithm.hをincludeしてないから起きるので、 該当ファイルを開き、 <code>#include &lt;algorithm&gt;</code> を加える</p> <p><a href="https://kazuyaujihara.wordpress.com/2016/03/29/visual-c-2015-%E3%81%A7%E3%80%81std-%E3%81%AB-min%E3%82%84max-%E3%81%8C%E3%81%AA%E3%81%84%E3%81%A8%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%8C%E5%87%BA%E3%82%8B%E5%A0%B4%E5%90%88/" title="None" target="_blank">Visual C++ 2015 で、std に minやmax がないとエラーが出る場合 | Kazuya Ujihara&#39;s Blog</a> </p> <p>もしエラーが出ないで終了した場合、 <code>lib</code>の中に<code>Modules_d.lib</code>ができていないなら失敗しているので、 「ビルド &gt; Modulesのクリーン」と「ビルド &gt; ソリューションのクリーン」 を実行して再度バッチビルドをしてみると良い気がする。</p> <h2>ライブラリのビルド</h2> <p>最後に、それぞれ勉強したい章のライブラリをビルドする。 ここでは2章に当たる<strong><code>2DGraphics1</code></strong>をビルドしていく。</p> <ul> <li><code>GameLib2012\src\GameLibs\2DGraphics1\GameLib.sln</code> を開く</li> <li>「ビルド &gt; ソリューションのビルド」を選ぶ</li> </ul> <p>環境変数の設定がうまくいっていればここでビルドは成功する。しかし、出力を見るとあらかじめ含まれているファイルによってビルドしたファイルがコピーに失敗している。</p> <blockquote> <p>1&gt; サブディレクトリまたはファイル C:\GameLib2012\2DGraphics1\include は既に存在します。</p> <p>1&gt; サブディレクトリまたはファイル C:\GameLib2012\2DGraphics1\include\GameLib は既に存在します。</p> <p>1&gt; サブディレクトリまたはファイル C:\GameLib2012\2DGraphics1\include\GameLib\Base は既に存在します。</p> <p>&hellip;</p> </blockquote> <p>これは「プロジェクト &gt; プロパティ」の中にある、「ビルドイベント &gt; ビルド後のイベント」で設定されているコマンドのファイルコピーによるもの。</p> <p>なので、これらのファイルを削除し再度ビルドする。</p> <p><code>GameLib2012\2DGraphics1\</code> 以下にある、<code>include</code>と<code>lib</code>を削除し、 もう一度ソリューションをビルドする。うまくいけば、きちんとどちらのディレクトリ内にもファイルができているはず。</p> <h2>サンプルコードの実行</h2> <p>これでライブラリのビルドは終わったので、試しに<code>drawPixels</code>プロジェクトをビルドしてみる。</p> <ul> <li><code>GameLib2012\src\02_2DGraphics1\2DGraphics1.sln</code> を開く</li> <li>ソリューションエクスプローラーから<code>drawPixels</code>を右クリックし、「<code>デバッグ &gt; 新しいインスタンスを開始</code>」</li> </ul> <p>しばらくするとデバッガーが起動し、ウィンドウが現れる。</p> <p><img src="/entry/game-programmer-book-build-vs2015/drawPixels.png" alt="drawPixels" title="None"/> </p> <p>お疲れ様でした!</p> <p>あとは他の章も同様にライブラリをビルドしていけば動くはず。とりあえず3章の途中までは<code>max</code>と<code>min</code>を使うために<code>#include &lt;algorithm&gt;</code>を加えるだけでエラーは無くなってビルド出来ていた。 (まだ先の章まで進んでないので他の罠もあるかも)</p> <h2>まとめ</h2> <p>最初はエラーの内容自体がよくわからずに苦戦したが、色々試行錯誤しているうちにWindowsやVisualStudioの設定自体にも慣れてきたので結果的には良かった。が、普通に初心者が勉強し始めるときはこういうところで躓くといきなり心が折られると思うのでこの情報が誰かの役に立てばいいなと思う。Windowsの開発環境構築に関してももう少しまとまったら別途記事を書きたい。</p> <h4>余談: 空のプロジェクトを作って始める場合</h4> <p>「新規作成 &gt; プロジェクト」 を選び、テンプレートから<code>Visual C++</code>を選択する。</p> <p>テンプレートがインストールされていない場合、右のパネルからその項目を選んでインストールする。</p> <p>新規に作る場合は、ここの 「<code>Win32コンソール アプリケーション</code>」か 「<code>Win32プロジェクト</code>」から空のプロジェクトを作成することになると思う。</p> Windows Thu, 01 Sep 2016 04:49:18 +0900 BitBarプラグイン「bitbar-appstore」を作った http://log.moremorefor.net/entry/bitbar-appstore <p>特定のiOSアプリのランキングを表示するBitBarプラグイン「 <a href="https://github.com/moremorefor/bitbar-appstore" title="None" target="_blank">bitbar-appstore</a> 」を作った。</p> <p><img src="/entry/bitbar-appstore/bitbar-appstore.png" alt="bitbar-appstore" title="None"/> </p> <p><a href="https://getbitbar.com/" title="None" target="_blank">Bitbar</a> は、Macのメニューバーに任意のスクリプトを実行した結果を表示するアプリ。このプラグインはPython2.xが入っていれば動くと思う。<em>(Mac標準はPyton2.7とかのはずなので普通なら誰でも使えるはず。)</em></p> <p>デフォルトでは1時間に一度更新する。変えたい場合は、ファイル名の<code>1h</code>を変更すればいい。</p> <h2>設定</h2> <p>設定は、ファイル内で、国コードを表示するかの設定と、表示したい分だけFeedを登録しておくだけ。ランキングの種類とジャンルについては、ファイル内で定義してあるdictから選べるようにした。配列に複数書いておけばその分表示される。</p> <div class="highlight"><pre><span class="n">show_country</span> <span class="o">=</span> <span class="bp">True</span> <span class="n">feed_settings</span> <span class="o">=</span> <span class="p">[</span> <span class="p">{</span> <span class="s">&#39;RANKING_TYPE&#39;</span><span class="p">:</span> <span class="n">RANKING_TYPE</span><span class="p">[</span><span class="s">&#39;Top Free Applications&#39;</span><span class="p">],</span> <span class="c"># See list in file</span> <span class="s">&#39;GENRE&#39;</span> <span class="p">:</span> <span class="n">GENRE</span><span class="p">[</span><span class="s">&#39;Games&#39;</span><span class="p">],</span> <span class="c"># See list in file</span> <span class="s">&#39;COUNTRY&#39;</span> <span class="p">:</span> <span class="s">&#39;jp&#39;</span><span class="p">,</span> <span class="c"># Country code (ISO 3166-1 alpha-2)</span> <span class="s">&#39;LIMIT&#39;</span> <span class="p">:</span> <span class="mi">200</span><span class="p">,</span> <span class="c"># 1~200</span> <span class="s">&#39;APP_ID&#39;</span> <span class="p">:</span> <span class="mo">0000000000</span> <span class="c"># Your app id</span> <span class="p">}</span> <span class="p">]</span> </pre></div> <h2>仕組み</h2> <p><a href="https://rss.itunes.apple.com/" title="None" target="_blank">iTunes RSS Feed</a> からjsonで取ってきて<code>print</code>してるだけ。一番目と二番目の出力の間に<code>---</code>を<code>print</code>して、一番目を固定表示にしている。iTunes RSS Feedだと、ランキングは200位までしか取ってこれないらしく、200位圏外の場合は<code>---</code>と表示される。</p> <p>ランキングの種類はiTunes RSS Feed、ジャンルについては、 <a href="https://affiliate.itunes.apple.com/resources/documentation/genre-mapping/" title="None" target="_blank">Genre IDs Appendix</a> から取ってきて定義した。</p> <h2>まとめ</h2> <p>BitBarのプラグイン、超簡単に作れて便利なので楽しい。GooglePlay版も作りたいけどRSSやAPIが無いようなので、作るなら誰かが作ったライブラリとか使おうかなと思ってる。</p> Python Fri, 11 Mar 2016 21:13:06 +0900 PSD2FlintoというFlinto for MacのPhotoshopスクリプトを作った http://log.moremorefor.net/entry/psd2flinto-release <p>Photoshopのドキュメントを <a href="https://www.flinto.com/ja/mac" title="None" target="_blank">Flinto for Mac</a> (以下、Flintoと記述)のドキュメントとして書き出しすることができる <a href="https://github.com/moremorefor/PSD2Flinto" title="None" target="_blank">PSD2Flinto</a> というスクリプトを作った。</p> <p><img src="/entry/psd2flinto-release/psd2flinto1.png" alt="PSD2Flinto" title="None"/> </p> <p><img src="/entry/psd2flinto-release/psd2flinto2.png" alt="PSD2Flinto" title="None"/> </p> <p>こんな感じでレイヤーカンプの画面をそのままFlintoのドキュメントとして書き出せる。<em>(ただし残念ながら処理はそんなに早くない)</em></p> <p>現在はFlintoのv1.2系に対応していて(v.1.3系でも動きはする)、v1.3系の目玉機能であるsketchからの再読み込みへの対応がスクリプト単体だと難しいことがわかったので一旦の区切りにとした。再読み込み機能は難しいが、他の対応出来る機能はこれからも対応しようと思っている。(再読み込み機能対策については後述)</p> <h2>対応機能</h2> <p>必要な機能は割りと入れられたかなと思っていて、</p> <ul> <li>テキストレイヤー</li> <li>スマートオブジェクト</li> <li>クリッピングマスク</li> <li>レイヤーマスク</li> <li>レイヤースタイル</li> <li>調整レイヤー</li> <li>レイヤーカンプの複数書き出し</li> </ul> <p>辺りはサポートしていて、</p> <ul> <li>書き出しパネルのサポート</li> <li>ドキュメントの状態に応じたエラー処理</li> <li>書き出しの高速化</li> </ul> <p>などもしている。</p> <h2>きっかけ</h2> <p>このスクリプトを作ることになったきっかけは、去年開催された <a href="http://connpass.com/event/22125/" title="None" target="_blank">Flinto×Cookpad〜プロトタイピング開発のいま〜</a> というFlintoのミートアップに参加させていただいたことだった。 <a href="http://rebuild.fm/115/" title="None" target="_blank">Rebuild.fm</a> でも宣伝されていたので知っている人も多いかな?と思う。</p> <p>参加出来ることがわかった時に、せっかく参加するなら質問したいなと思って、一通り機能を使ったり <a href="https://www.flinto.com/ja/tutorial_videos" title="None" target="_blank">チュートリアル</a> を見たり、他のプロトタイピングツール( <a href="https://www.invisionapp.com/" title="None" target="_blank">InVision</a> や <a href="http://www.pixate.com/" title="None" target="_blank">Pixate</a> など)との違いを考えてみたりしてから行った。</p> <p><img src="/entry/psd2flinto-release/meetup.png" alt="Meetup" title="None"/> </p> <p>で、参加したところ質問タイムが予想通りあったので、3つも質問させていただいた(3つ目は最後少し強引に訊いてしまった感がありすみません&hellip;)。その3つ目の質問が、</p> <blockquote> <p>「Sketch用のプラグインはあるけど、Photoshop用のものは用意される予定はありますか?もしくは、画像とjsonからインポートできる機能でもいいのですが&hellip;!」</p> </blockquote> <p>という内容で、そこで、</p> <blockquote> <p>「実はSketch用のプラグインはそうなっているので、リバースエンジニアリングすれば出来ます!」</p> </blockquote> <p>という回答を頂けた。なので、じゃあ作れるかも?ということで、その日のうちに帰ってからSketchプラグインのスクリプトを読んで作り始め、次の日には動くものが出来た。</p> <p>一箇所だけCocoascript力が足りずによくわからないところがあり悩んでいたら、その箇所は@naanさんに直接リプライでアドバイスをいただき、無事に動くところまでもっていけた。ありがとうございます!</p> <p><img src="/entry/psd2flinto-release/twitter.png" alt="Twitter" title="None"/> </p> <p>(最初、Flintoで開くとディレクトリがバイナリになってしまう仕様がわかってなくて???ってなってた)</p> <h2>Photoshopスクリプトの問題</h2> <p>ひとつ目は、現状できちんと動いてはいるが、やはりベクターが主になっているSketchと比べると、Photoshopスクリプトは書き出しなどの<strong>処理が遅い!</strong>。これはおそらくPhotoshopのスクリプトであるExtendScriptのVMが遅いのも原因だと思うので、多分どうにもできない&hellip;。</p> <p>ふたつ目は、冒頭で書いたように、Flinto v1.3系の再読み込み機能に対応するために必要なパラメータが、Photoshopのレイヤーには用意されていないということ。具体的にはUUID的に使えるプロパティが存在しないので、同じ機能を作るには別の方法を考えないといけない。</p> <h3>Generatorプラグインにする</h3> <p>なので、今はGeneratorというPhotoshopのプラグイン版のPSD2Flintoを作っている。Generatorは処理が早いし、非同期で動かせる。割りと形にはなってきているが、リリースに必要な作業がまだ漠然としていたり、再読み込み機能に対応するためのid処理の検証などに時間がかかりそうなので、ちょっとまとまった時間がとれるまで置いている。</p> <p><div class="twitter-tweet"><blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Generator-PSD2Flinto、大体出来てきた。最適化前だけど生成にこのくらいのpsdで12,459ms。jsxと比べると圧倒的に速い。ちょっと遅いかもだけどバックグラウンドでも動くのは強い。 <a href="https://twitter.com/hashtag/flinto?src=hash">#flinto</a> <a href="https://t.co/gjjkm3rFOI">pic.twitter.com/gjjkm3rFOI</a></p>&mdash; moremorefor (@more_more_for) <a href="https://twitter.com/more_more_for/status/680682909129285632">2015, 12月 26</a></blockquote></div> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>ということでちまちま作っていこうかなと思っている。それまでは普通のPSD2Flintoを使っていただくということで&hellip;。</p> <h2>まとめ</h2> <p>作ってみて、スクリプトやプラグインの勉強が捗っているので個人的な勉強としても良かった。続けていきたい。</p> <p>Flinto for Macはアプリの詳細なモックを作るのに非常に強力なツールだと思うのでぜひ使ってみてください。もしPhotoshopを使っている方は <a href="https://github.com/moremorefor/PSD2Flinto" title="None" target="_blank">PSD2Flinto</a> も使ってみて感想くれると嬉しいです (_ _)</p> Photoshop Thu, 18 Feb 2016 09:33:01 +0900 UIデザインワークフロー・ファイル管理考2015 http://log.moremorefor.net/entry/ui-materials-2015 <h4>はじめに</h4> <p><em>NOTE: この記事は以下の条件上で考えた構成です</em></p> <ul> <li>Cocos2d-xでiOS/Android向けのゲーム</li> <li>このアプリは主に3人で作っており、UIデザイナー&amp;グラフィッカー(自分)とフロント&amp;サーバーエンジニア(以下、エンジニアと記述)の2人に絞った構成(もう一人はディレクター&amp;プランナー)</li> </ul> <p>UIをどういう風に考えて作ったらいいのかという記事は多いけど、<strong>実務上どういうフローや画像管理を経て制作されているという具体的な事例があんまり出てこないので、もっとみんなどうやっているのか知りたい。</strong>というのがこの記事を書いた目的です。なので、ここで書いたことに対する質問・意見・自分はこうしている、みたいなことを記事に書いたりフィードバック欲しいなぁ&hellip;と思ってます。</p> <p>個々の環境によってベストプラクティスが変わってくる部分だと思うので、こうすべきという内容ではなく、こういう風にしてみました、という意味で記事は書きました。現状の構成には今のところ破綻はなく、満足しています。</p> <h3>今回題材にするアプリ</h3> <p><img src="/entry/ui-materials-2015/huntcook.png" alt="Huntcook" title="None"/> 去年開発・リリースして今は運用や国際化を進めている <a href="http://selectbutton.jp/apps/huntcook" title="None" target="_blank">ハントクック</a> というゲームアプリでの構成です。<em>(ダウンロードして遊んでみてください!)</em></p> <p>今回の目的としては、一つは、各種素材を作ってエンジニアに投げたら実装上がってくるまで関わらなくて済む状態にすること、もう一つは、あとから見てもアプリの構成がどうなっているのかなるべくわかりやすくする、を大きな目的としています。</p> <ul> <li>ワークフロー <ul> <li>プレビュー</li> <li>アプリモック</li> </ul></li> <li>ファイル管理 <ul> <li>ディレクトリ構成とファイル名の規則</li> <li>シンボリックリンクによる管理</li> <li>9スライス管理</li> <li>他の細かい指定管理</li> </ul></li> <li>レイアウト管理</li> </ul> <h2>ワークフロー</h2> <p>構成としては以下のようになっていて、まずはデザインを作って相談し、決まったたところで自分が作成した素材を切り出して専用の素材リポジトリにpushし、その素材をエンジニアがpullして一旦処理を挟んでからプロジェクトに入れて使用するという構成にしています。</p> <p>運用に入ってからは、デザイン作業が先行したままでアップデート作業などもあるので、リポジトリが分かれているとやりやすいなと思っています。</p> <p><img src="/entry/ui-materials-2015/workflow.png" alt="Workflow" title="None"/> </p> <p>前処理のところは、例えば、素材リポジトリではディレクトリが別れていて、前処理の時にディレクトリを1個にまとめてアプリで使う、などをしています。</p> <p>各種素材と指示書などを渡した時点でデザイナー側の作業は一旦終わり、実装が上がってくるまでほぼ何もする必要が無いです。</p> <h3>1. プレビュー</h3> <p>基本的にまず出来た画像はプレビューとしてアップします。Slackに上げてちまちま進捗を見せますが、Slack上で簡単な検証が一通り済んだものは、社内のプレビューサイトにアップしておきます。これはNodeで作成されており、S3にアップすれば見れるようになっています。S3の管理には <a href="https://itunes.apple.com/jp/app/3hub/id427515976?mt=12" title="None" target="_blank">3Hub</a> を使っており、Finderの延長感覚で使えるので便利です。(もう少し使いやすいツール欲しいですが&hellip;)</p> <p><img src="/entry/ui-materials-2015/previewer.png" alt="Previewer" title="None"/> </p> <h3>2. アプリモック</h3> <p>次にデザイン決定するために、デザインが一旦出来た段階ですべての画面のプロトタイプモックを作成します。ゲームなので柔軟に動きのモックが作れるように、Flashを使ってAIRアプリとして書きだす様にしています。</p> <p><img src="/entry/ui-materials-2015/huntcook.gif" alt="Huntcook" title="None"/> </p> <p>AIR(Flash)でモックを作るメリットは、</p> <ul> <li>iOSでもAndroid端末上でも確認できる</li> <li>swfも書き出せばブラウザ上でも見れる</li> <li>音が入れられる</li> <li>当たり前だけど他のモックツールよりも遥かに柔軟に作れる</li> </ul> <p>モックにはできるだけ時間をかけない、をポリシーにしてモックの中身の作り方は結構雑に作っていて、フレームにAS3を書きまくっていったので、今では全ての画面が入ったことで結構重くなっています。めんどくさくなった時点でこういうのは終わりなのでとにかくきちんと動きが見れればそれ以外は多少雑でも良しとしていました。(次はよく使うものはライブラリとかにしておきたい)</p> <p><img src="/entry/ui-materials-2015/flash.png" alt="Flash" title="None"/> </p> <p>基本的にはこの段階で実装までのすべての検証を済ませます。UIの見直し・アップデートする時に問題になりそうなことの検討・画像の切り出しをどういう風に行なうか&hellip;などなどです。実際に実装してみて、仕様変更が入ることはある程度仕方ないですが、実装段階で問題が見つかることは、モック作成を繰り返すことで基本的にすべて潰せていたかなと思います。</p> <p>このFlashを使用した雑モックの作り方についてはまた別記事で書きたいなぁと思っています。</p> <h2>ファイル管理</h2> <p>次に素材リポジトリの詳細ですが、例えば、ハントクックでは以下の様になっています。</p> <h3>1. ディレクトリ構成とファイル名の規則</h3> <p>画像はシーン毎にディレクトリ分けされており、共通パーツは<code>common</code>、今後更新があったり色々なシーンで使用されることが予想されるイラスト素材は<code>illust</code>にまとめるように管理しています。ここには描いてないですが各シーンはさらにサブシーンなどに細かくディレクトリに分割されています。</p> <p><img src="/entry/ui-materials-2015/directories.png" alt="Directory" title="None"/> </p> <p>画像名は、<strong>シーン名_サブシーン名_パーツ名.png</strong>の様な命名にしており、名前が競合しない対策としてこういう命名にしています。</p> <p><img src="/entry/ui-materials-2015/filename.png" alt="FileName" title="None"/> </p> <p>Cocos2d-xではディレクトリを分けることで競合を避けられますが、エンジニアがディレクトリ名を書かなくて済むように、プロジェクトに入れる前処理で、1個のディレクトリにすべて入れる構成にしています。これは国際化対応のためでもあります。</p> <h3>2. シンボリックリンクによる管理</h3> <p>上記の構成はまぁ普通だと思いますが、これはあまりやられてないことかなと思います。</p> <p>今回は画像が大量にあるということで、更新が発生するであろうイラストの画像を<code>illust</code>ディレクトリにまとめておきたかった。が、しかし、まとめてしまうと、各シーンでどのイラスト画像が使われているのかわからなくなってしまう。cooking画面ではfood_sだっけ?food_lだっけ?みたいなことになる。という問題がありました。</p> <p><img src="/entry/ui-materials-2015/forget.png" alt="Forget" title="None"/> </p> <p>担保したかったのは、<strong>ファイルシステム上でアプリ上の使用画像がわかる</strong>ということ。あとからリポジトリの構成を見ればどの画像が使われているのかわかるようにしたい。</p> <p>そこで今回は相対シンボリックリンクを使ってみました。</p> <p>例えば、<code>illust</code>内の<code>food_l</code>を<code>_food_l</code>としてcooking以下にシンボリックリンク以下で置いておく。そうすればあとから見てもcookingの画面で使われている料理の画像は<code>food_l</code>だとわかるようになります。</p> <p><img src="/entry/ui-materials-2015/symlinkDir.png" alt="Directory" title="None"/> </p> <p>今回は<strong>アンダースコアが付いているものはシンボリックリンクディレクトリ</strong>だというルールにしておいたので、どれがイラスト画像なのかがわかり、cooking画面を更新するときに更新漏れが発生することも少なくなる。という想定です。</p> <p>相対シンボリックリンクにしておけば、そのままgitに入れても問題なくシンボリックリンクが機能するのもポイントでした。</p> <p>しかしシンボリックリンクをコマンドラインから貼るのは、普段Finder系のGUIを主に使う身としてはめんどくさすぎる&hellip;。</p> <h4>ツールを作る</h4> <p>ので、GUIで相対シンボリックリンクを貼れるアプリをAIRで雑に作りました。フォントとか色々ちょっとあれですが気にせず&hellip;。動けばいいんですよ&hellip;。</p> <p><img src="/entry/ui-materials-2015/symlinks.png" alt="Symlinks" title="None"/> </p> <p>黒いところにそれぞれのファイルやディレクトリを放り込んでボタン(下の灰色のやつ)を押すと相対シンボリックリンクを貼ってくれるだけ。AIRのNativeProcessを使って裏でPythonを使ってシンボリックリンクを貼っています。</p> <h3>3. 9スライス画像管理</h3> <p>次に9スライス画像も以前からもっと便利にしてみたいなと思っていて今回取り組んでみました。具体的には、エンジニアが楽なように、こっちで管理して最小サイズの画像とパラメータだけ渡す形にしたかった、のです。で、色々見ていたらこれを見つけたので使わせていただきました。</p> <p><a href="http://qiita.com/kyubuns/items/4327bb38ff22989ba7ed" title="None" target="_blank">[Unity] 自動的にUI素材を9SlicedSprite化する - Qiita</a> </p> <p>しかしRubyのスクリプトでUnity用&hellip;</p> <h4>ツールその2</h4> <p>なのでこれもツールを作りました。画像を放り込めば最小サイズの画像を吐き出しつつ、Cocos2d-x用のコードを吐きます。スライス後の画像が正しく縮小されているかの確認に使え、実際何度かそれで不具合を見つけられました。 <img src="/entry/ui-materials-2015/9slicer.png" alt="9Slicer" title="None"/> </p> <p>吐き出したコードは(形式はなんでも良かったけれど)とりあえずymlにまとめ、9sliceというディレクトリにシーン毎に元画像と一緒に置き、ymlはシンボリックリンクを張るようにしました。</p> <p>これでファイルシステム上で、小さい画像はymlを見れば9スライス用のコードがあるので、エンジニアにもファイルシステムを直接見てもらえばわかるようになります。このアプリももう少しちゃんとしてから公開したいなと思ってはいます&hellip;思っては&hellip;。</p> <h3>4. 他の細かい指定管理</h3> <p>キャラクターの位置や一部の画像サイズ・影の位置のjsonなどはデザイナーが生成して、それをアプリでそのまま使ってもらうようにしています。細かい指定が必要なところはこうしておくことで、デザイナーの裁量で進められるようになります。(ただし、jsonのバリデーションをちゃんとしないと怖い)</p> <p>jsonの生成は、レイヤー名を簡易なパーサーでパースして生成するスクリプトを使っており、生成な必要なレイヤーがpsd上でもわかるようにしています。ただこれもレイヤー名が変わってしまうと不具合の原因になるのでもう少しいい仕組みにしないとなと思っています。<em>(これについてはPhotoshopの画像アセット機能も同様の怖さがあると思っています)</em></p> <h2>レイアウト管理</h2> <p>画像などの管理はこれで出来たので、あとはレイアウト指示書を作ります。これには今回自作ツールを作りました。<em>(前からどういうツールがあったらいいか検討してはいていて、ある時点からあまりにも切羽詰まってきてこれは今作らないとやばいと決意して深夜5日間くらいで作った)</em></p> <p>レイヤーを選択してポチポチやれば中間ファイルが作成され、そこからjsonと画像を書き出して、ビューワーに入れると見れるようになるというPhotoshopのスクリプトセットになっており、ビューワーはMithril+Nodeで作っています。</p> <p><img src="/entry/ui-materials-2015/layouter.png" alt="Layouter" title="None"/> </p> <p>SketchであればZeplinや、psdでならAvocodeなど似たようなツールはありますが、作った理由はいくつかあります。</p> <ul> <li><strong>Cocos2d-xは左下座標系</strong></li> <li>画像同士の相対位置が知れるツールがなかった(と思う)</li> <li>エンジニアは書きだされた素材の位置やサイズだけが知りたいのであって、レイヤー全てを見れるのは情報過多だし選択するのが面倒(Avocodeとか)</li> <li>Photoshopに対応した良いツールがない</li> <li>完全自動の処理で理想的な指示書を作るのが難しい</li> </ul> <p>このツール、公開出来るように作っていましたが、まだ他の人がどういう機能を必要としているのかわからない部分も多いので、公開していないです。こういう機能があったら使いたいなぁみたいな情報があれば、ぜひ教えて下さい。今はこれをGeneratorバージョンに移行し、もう少し自動化出来るように検討をしています。</p> <h2>まとめ</h2> <p>現状上記の構成で上手く回っていて、運用段階になってみてさらにちゃんと構成をきちんと整理しておいて良かったなと思います。あと、ワークフロー的にも自分がここまでをやればいいというのがハッキリしているので、コミュニケーションに関するストレスが全く無く、スケジューリングもしやすくなったのが今のところ良いかなと思っています。</p> <p>あと、ついでにこの記事でひとつ主張したいことがあるとすれば、デザイナーでも自分が必要としているツールなどは自分自身で作るしか無いかなと思います(特にそれがちょっとしたものだと)。誰かに頼んでそういうツールを作ってもらうというのはありですが、UIや使い勝手を考えて伝えて作ってもらうのは大変です。作った後でやっぱり違ったなんてことも作ってるとよくありますし。プロジェクトが忙しい時に自分で自分を助けられる手段を持っておくのは有効だと思うので、デザイナーもプログラムを少し触れる用になっておくと便利かなーと思います。<em>(多少ポジショントーク気味ですが)</em></p> UI Fri, 12 Feb 2016 10:12:01 +0900 JSXExecutorというPhotoshop拡張を作った http://log.moremorefor.net/entry/jsxexecutor <p>jsxファイルのあるディレクトリを読み込んで、Photoshopのパネル上から直接実行する <a href="https://github.com/moremorefor/JSXExecutor" title="None" target="_blank">JSXExecutor</a> という拡張を作った。</p> <p><img src="/entry/jsxexecutor/jsxexecutor.png" alt="JSXExecutor" title="None"/> </p> <p>同じような拡張である <a href="http://chuwa.iobb.net/tech/archive/2015/05/jsxlauncheraips.html" title="None" target="_blank">JSXLauncher</a> と <a href="https://ics.media/entry/2302" title="None" target="_blank">JSFLTool</a> にインスパイアされてる。</p> <p>同じような拡張があるのになぜ作ったかというと、</p> <ul> <li>JSFLToolはFlash専用の拡張</li> <li>JSXLauncherは複数のディレクトリを読み込めない</li> <li>JSXLauncherはjsx内のデバッグ用メソッドが一部動かない</li> </ul> <p>ということで、2つの拡張のいいとこ取り+αな拡張が欲しかった。<em>(※現状JSXExecutorは複数ディレクトリ対応はまだ出来てない)</em></p> <h2>インストール</h2> <p>Githubに書いてあるが、</p> <ol> <li>JSXExecutor.zxpを <a href="https://github.com/moremorefor/JSXExecutor/raw/master/bin/JSXExecutor.zxp" title="None" target="_blank">ダウンロード</a> する</li> <li>CC・CC2014なら <a href="https://www.adobe.com/jp/products/extension-manager.html" title="None" target="_blank">Adobe Extension ManagerCC</a> 、CC2015なら <a href="http://zxpinstaller.com/" title="None" target="_blank">ZXPInstaller</a> を使ってインストール出来る</li> </ol> <h2>どのように使うか</h2> <p>自分のユースケースとしては、</p> <ul> <li>ちょっと試したいjsxなどを一つのディレクトリにどんどん作って貯めていく</li> <li>開発中のjsxを各バージョンのPhotoshopから確認できる</li> <li>業務で使うjsxを一個のディレクトリに入れてgitで管理・共有する</li> <li>プロジェクト毎に専用のjsxディレクトリを読み込む<em>(※これは複数ディレクトリに対応後)</em></li> </ul> <p>などを想定している。Photoshopの再起動無しでjsxを読み込めるのが、自分の様にバンバンjsxを書いて使う人にはすごく便利なんじゃないかなと思う。デバッグ用の<code>$.write</code>などがきちんと動くのも便利。</p> <h2>実装について</h2> <p>この拡張はCommon Extensibility Platform(CEP)という拡張機能を利用している。詳しくは「 <a href="http://aphall.com/2014/08/cep-mega-guide/" title="None" target="_blank">CEPスーパー メガ ガイド: HTML5+Node.jsでAdobeのツールを拡張する | aphall.com</a> 」を見ていただけると一番早いと思う。</p> <p>ただし、ここで書かれているのはCEP5という仕様についてで、今回はAdobe CCバージョンでも動かすために、Node.jsが使えないCEP4という仕様に基づいて制作した。<em>(CEP5はCC2014から対応)</em></p> <p>なので、HTMLでUIを構築し、jsとjsx間をやり取りしながら実装する形だけになっている。jsからjsxを実行するのはすべて非同期で行われるので、今回は「 <a href="https://github.com/kriskowal/q" title="None" target="_blank">q</a> 」のDeferred(Promise)を利用してメソッドチェーンで続ける形にした。</p> <div class="highlight"><pre><span class="kd">var</span> <span class="nx">jsxInterface</span> <span class="o">=</span> <span class="nx">JSXInterface</span><span class="p">.</span><span class="nx">getInstance</span><span class="p">();</span> <span class="nx">jsxInterface</span><span class="p">.</span><span class="nx">evaluateJSX</span><span class="p">(</span><span class="s2">&quot;getFileList&quot;</span><span class="p">,</span> <span class="p">{</span><span class="nx">scriptpath</span><span class="o">:</span><span class="nx">scriptpath</span><span class="p">})</span> <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">filesObj</span><span class="p">)</span> <span class="p">{</span> <span class="nx">filesObj</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">filesObj</span><span class="p">);</span> <span class="kd">var</span> <span class="nx">scriptpath</span> <span class="o">=</span> <span class="nx">filesObj</span><span class="p">[</span><span class="s2">&quot;scriptPath&quot;</span><span class="p">];</span> <span class="kd">var</span> <span class="nx">files</span> <span class="o">=</span> <span class="nx">filesObj</span><span class="p">[</span><span class="s2">&quot;filepaths&quot;</span><span class="p">];</span> <span class="k">return</span> <span class="p">[</span><span class="nx">scriptpath</span><span class="p">,</span> <span class="nx">files</span><span class="p">];</span> <span class="p">})</span> <span class="p">.</span><span class="nx">spread</span><span class="p">(</span> <span class="p">...</span> </pre></div> <p>jsからjsxの実行については、CSInterface.evalScript()というCEPのライブラリのメソッドを利用するので、それをいい感じにPromiseでラップして利用できるように、JSXInterfaceをいうクラスを作っている。これは「 <a href="https://github.com/adobe-photoshop/generator-core" title="None" target="_blank">Generator</a> 」という別のPhotoshop拡張機能の仕組み内で書かれている方法をベースにした。</p> <p>下調べがちょっと足りてなく、ライブラリで用意されている一部の機能も今回jsxで作ってしまったので、本当は全体的にもう少し簡単に書けると思う。</p> <p>UI部分については「 <a href="http://topcoat.io/" title="None" target="_blank">Topcoat</a> 」や「 <a href="http://refills.bourbon.io/" title="None" target="_blank">Refills - Patterns</a> 」を使うようにしているので、あまり手をかけていない。</p> <h2>デバッグ用メソッドを動かす</h2> <p>jsxから別のjsxを呼ぶには<code>$.evalFile</code>を使えばできるが、これを使用した場合、呼ばれたjsx内の<code>$.write</code>などがExtendScriptToolKitの方のコンソールにきちんと値を出力してくれない。</p> <p>これをうまく動かすには、Photoshop内からjsxを参照して呼ぶのと同じ方法を使えばいい。Photoshopの裏APIを動かすActionDescripterを利用する。</p> <div class="highlight"><pre><span class="kd">function</span> <span class="nx">executor</span><span class="p">(</span><span class="nx">args</span><span class="p">)</span> <span class="p">{</span> <span class="kd">var</span> <span class="nx">idAdobeScriptAutomationScripts</span> <span class="o">=</span> <span class="nx">stringIDToTypeID</span><span class="p">(</span> <span class="s2">&quot;AdobeScriptAutomation Scripts&quot;</span> <span class="p">);</span> <span class="kd">var</span> <span class="nx">desc1</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ActionDescriptor</span><span class="p">();</span> <span class="kd">var</span> <span class="nx">idjsCt</span> <span class="o">=</span> <span class="nx">charIDToTypeID</span><span class="p">(</span> <span class="s2">&quot;jsCt&quot;</span> <span class="p">);</span> <span class="nx">desc1</span><span class="p">.</span><span class="nx">putPath</span><span class="p">(</span> <span class="nx">idjsCt</span><span class="p">,</span> <span class="k">new</span> <span class="nx">File</span><span class="p">(</span> <span class="nx">args</span><span class="p">[</span><span class="s2">&quot;path&quot;</span><span class="p">]</span> <span class="p">)</span> <span class="p">);</span> <span class="kd">var</span> <span class="nx">idjsMs</span> <span class="o">=</span> <span class="nx">charIDToTypeID</span><span class="p">(</span> <span class="s2">&quot;jsMs&quot;</span> <span class="p">);</span> <span class="nx">desc1</span><span class="p">.</span><span class="nx">putString</span><span class="p">(</span> <span class="nx">idjsMs</span><span class="p">,</span> <span class="s2">&quot;undefined&quot;</span> <span class="p">);</span> <span class="nx">executeAction</span><span class="p">(</span> <span class="nx">idAdobeScriptAutomationScripts</span><span class="p">,</span> <span class="nx">desc1</span><span class="p">,</span> <span class="nx">DialogModes</span><span class="p">.</span><span class="nx">NO</span> <span class="p">);</span> <span class="k">return</span> <span class="kc">true</span><span class="p">;</span> <span class="p">}</span> </pre></div> <p>今回はこんな感じでjsxを用意しておいて、ここに実行したいpathを渡して利用するようにした。初回の起動に多少のラグが発生するときもあるが、概ね問題なく動くはず。</p> <h2>まとめ</h2> <p>週末1日でさくっと作れるかなと思ったら意外とそれから数日かかってしまった。代わりにCEPで拡張を作るのにも大分慣れたので勉強になってよかった。これで今作っている別のjsxの各種実験が捗りそう。</p> Photoshop Thu, 14 Jan 2016 01:57:55 +0900 Adobe CC2015にzxp形式の拡張機能をインストールする http://log.moremorefor.net/entry/zxp-in-cc2015 <p>CC2015からはCC2014まで使っていたAdobe Extension ManagerによるインストールがDeprecatedになり、直接的なzxp形式の拡張のインストールが出来なくなってる。</p> <blockquote> <p>For CC 2015 and later, you can no longer install Add-ons directly using Extension Manager. Users must install through the CC Desktop App.</p> </blockquote> <p><a href="https://www.adobeexchange.com/resources/20" title="None" target="_blank">Product Migration to Adobe Add-ons</a> </p> <blockquote> <p>IMPORTANT: Extension Manager Deprecated Extension Manager is obsolete in CC 2015. CC 2015 users MUST NOT use Extension Manager CC to install Add-ons.</p> </blockquote> <p><a href="https://www.adobeexchange.com/resources/19" title="None" target="_blank">Troubleshooting guide for Adobe Add-ons</a> </p> <p>なので、現在CC2015の公式な拡張機能のインストール方法としては、Creative Cloud Desktopアプリケーションをインストールしてファイル同期をONにして、 <a href="https://creative.adobe.com/addons" title="None" target="_blank">Adobe Add-ons</a> からインストールすることが推奨されている。</p> <h2>インストール出来ない</h2> <p>結論から言えば、自分の環境ではAdd-onsからはどうしても拡張がインストールできず、以下のどれかの方法でインストールすることになった。</p> <ol> <li>公式が配布している <a href="https://www.adobeexchange.com/resources/28" title="None" target="_blank">ExMan</a> を使う</li> <li>ExManのラッパーである <a href="http://zxpinstaller.com/" title="None" target="_blank">ZXPInstaller</a> を使う</li> <li>zipで提供されている拡張なら、マニュアルインストール出来る</li> </ol> <p>以下、経緯とそれぞれの詳細について書いていく</p> <h2>Add-onsからインストール出来ない</h2> <p>自分の環境だとどうしても拡張機能のインストールが出来なかった。まずは公式のトラブルシューティングを一通り見てみるが問題ない。</p> <p><a href="https://www.adobeexchange.com/resources/19" title="None" target="_blank">Troubleshooting guide for Adobe Add-ons</a> </p> <p>フォーラムを見てみるとExtention Manager CCを削除して拡張をインストールしなおせばリフレッシュされて直るというレスがあったので試す。</p> <blockquote> <p>lease uninstall Extension Manager, then reboot and uninstall or install any Adobe application (via the Creative Cloud Desktop application) - this will trigger a refresh of the list of installed applications. You can then reboot and retry an add-on installation via My Add-ons.</p> </blockquote> <p><a href="https://forums.adobe.com/thread/2046551" title="None" target="_blank">Add-ons don&#39;t sync | Adobe Community</a> </p> <p>ExtentionManagerCCを削除して、さらに全部のAdobeアプリを削除して(<em>あとで気づいたがそこまでしろとは書いてなかった</em>)、Macをリブート。Add-onsを再インストールして、Adobeアプリを再インストール、念のためAdd-onsをもう一度再インストールしてPhotoshopCC2015を開いてみたけど無理だった。</p> <p>アプリ全削除までしたのに&hellip;。辛い。</p> <h2>ExMan Command Line Tool</h2> <p>公式が、問題があってAdobe Add-onsから拡張をインストール出来ないユーザー向けに <a href="https://www.adobeexchange.com/resources/28" title="None" target="_blank">ExMan</a> というコマンドラインツールを提供している。Add-onsからはzxp形式でもダウンロードすることができるので、それを落としてきてExManから使うという想定になっている。</p> <p>上記リンクにはインストール方法の詳細も書いてあり、おそらくそれにしたがってやれば上手くインストール出来ると思う。(下記理由により直接使うのは試してはいない)</p> <p>しかし、自分の場合は拡張機能を作る側でもあり、ExManをインストールして自分で入れてくれとはユーザーに勧めにくい。ので、別の方法を探した。</p> <h2>サードパーティーのインストーラー</h2> <p>探してみるとExManのラッパーアプリが見つかった。</p> <ul> <li> <a href="http://zxpinstaller.com/" title="None" target="_blank">ZXPInstaller</a></li> <li> <a href="https://github.com/nvkzNemo/UberManager" title="None" target="_blank">nvkzNemo/UberManager</a></li> </ul> <p>ZXPInstallerの方もオープンソースになっており、見るとElectronでGUI部分を作り内部的にはExManを使っているのがわかる。</p> <p>これらを使えば、例えばGumloadなどで拡張機能を配布して、ZXPInstallerでインストールしてもらう、などということが可能になる。</p> <p>ZXPInstallerを試したところ、無事にインストールできた。(UberManagerは未確認)</p> <h2>マニュアルインストール</h2> <p>実は、拡張機能は指定のディレクトリにソースを置くだけでインストール可能になっている。もしすでにインストールした拡張機能があれば、</p> <ul> <li>CCの場合: <code>/Library/Application\ Support/Adobe/CEPServiceManager4/extensions/</code></li> <li>CC2014・2015の場合: <code>/Library/Application\ Support/Adobe/CEP/extensions/</code></li> </ul> <p>を見てみると、拡張機能があるのがわかる。</p> <p>なので、 <a href="http://guideguide.me/" title="None" target="_blank">GuideGuide</a> や、 <a href="http://ink.chrometaphore.com/" title="None" target="_blank">Ink</a> などの様に、zipでも提供されている拡張機能は、上記のディレクトリ以下に置いてアプリを再起動するだけでインストールすることが出来る。<em>(過去にインストールした拡張機能なども、移せばそのまま動かせたり、いじれば自己責任で動かせたりする)</em></p> <p>ちなみにこの方法で動かすことの出来る拡張はSigningされたものだけであり、自分で作った拡張はこの方法だけでは動かせない。詳しくは「 <a href="https://github.com/Adobe-CEP/CEP-Resources/wiki/CEP-6-HTML-Extension-Cookbook-for-CC-2015" title="None" target="_blank">CEP 6 HTML Extension Cookbook for CC 2015</a> 」を参照。</p> <h2>まとめ</h2> <p>普通にCC2015でzxp形式の拡張を使いたい場合、ZXPInstallerを使うのが一番手軽でいいと思う。Adobe Add-onsには痛い目を見させられたので、少なくともあと1年間は使わないなと思う。</p> Photoshop Thu, 07 Jan 2016 20:27:05 +0900 Flaskでブログエンジンを作ってデプロイするまでのまとめ http://log.moremorefor.net/entry/logpot-publish <p>本業は別なので、強制的に色んなことの勉強をするためにLogpotというシンプルなブログエンジンを作った。このブログがそう。ちまちま進めてきて、かなり前に大体出来てデプロイも済んでたけど、忙しくて細かいところ直すのに今になってしまった。</p> <p><img src="/entry/logpot-publish/logpot.png" alt="Logpot" title="None"/> </p> <p>とりあえず完成ソース: <a href="https://github.com/moremorefor/Logpot" title="None" target="_blank">moremorefor/Logpot</a> </p> <p>とその付属物</p> <ul> <li> <a href="https://github.com/moremorefor/gulp-bourbon-skeleton" title="None" target="_blank">moremorefor/gulp-bourbon-skeleton</a></li> <li> <a href="https://github.com/moremorefor/ansible-playbooks" title="None" target="_blank">moremorefor/ansible-playbooks</a></li> </ul> <p>機能としては、カテゴリとタグ(&hellip;ページはまだ無い)、複数画像アップロード、Markdown、コードハイライト、RSS、OGPなど。ブログ記事のURL(Wordpressでいうslug)と画像アップロード先のディレクトリ名を一緒にしたくて、そういう感じにしてあるけど、現状ちゃんとそういう仕組みに出来てなくて、記事を上げてからしか画像がアップできないというダメな感じになってしまっている。いずれ直す。</p> <hr> <p>以下、勉強したこと</p> <ul> <li>FlaskとそのExtension周り</li> <li>タスクランナーにGulpを使う</li> <li>Sassの設計</li> <li>サーバーセットアップ</li> <li>Ansibleでその自動化(+Vagrant)</li> <li>アプリケーションサーバー</li> </ul> <p>一通りやりたかったことは出来て色んな知識がついたと思う。</p> <h2>FlaskとそのExtension周り</h2> <p>Django使えばブログっぽいものはすぐ出来るだろうけどそれじゃ勉強の意味が無い。なのでFlaskで作る。</p> <p>今までもトークン発行用に使ったり、Twitterクローン的なものをちょっと作ったりしてたけど、そこまで構造化とか考えて使ったこと無かったので、いろんなモジュール入れてちゃんと使ってみたかった。</p> <p>Flaskのことについてはこの辺の本とか記事、コードを参考にさせてもらった。特にBlueprintで分割したり、循環importにならないようにアプリ全体をどういう構造にすればいいのかは大変参考にさせていただいた。日本語の情報は貴重でありがたい&hellip;。</p> <h4>本</h4> <ul> <li> <a href="http://shop.oreilly.com/product/0636920031116.do" title="None" target="_blank">Flask Web Development - O&#39;Reilly Media</a></li> <li> <a href="http://tatsu-zine.com/books/explore-flask" title="None" target="_blank">探検! Python Flask - 達人出版会</a></li> </ul> <h4>記事</h4> <ul> <li> <a href="http://methane.hatenablog.jp/entry/2012/12/05/134206" title="None" target="_blank">Flaskのカスタマイズについて - methaneのブログ</a></li> <li> <a href="http://methane.hatenablog.jp/entry/2012/12/24/214950" title="None" target="_blank">Flaskの闇 - methaneのブログ</a></li> <li> <a href="http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world" title="None" target="_blank">The Flask Mega-Tutorial - miguelgrinberg.com</a></li> </ul> <h4>Github</h4> <ul> <li> <a href="https://github.com/mkdocs/mkdocs/" title="None" target="_blank">mkdocs/mkdocs</a></li> <li> <a href="https://github.com/miguelgrinberg/flasky" title="None" target="_blank">miguelgrinberg/flasky</a></li> </ul> <hr> <p>次に、使ったExtensionはこの辺</p> <h4>Extension</h4> <ul> <li> <a href="https://github.com/flask-admin/flask-admin" title="None" target="_blank">Flask-Admin</a></li> <li> <a href="https://github.com/maxcountryman/flask-login/" title="None" target="_blank">Flask-Login</a></li> <li> <a href="https://github.com/miguelgrinberg/Flask-Migrate" title="None" target="_blank">Flask-Migrate</a></li> <li> <a href="https://github.com/smurfix/flask-script" title="None" target="_blank">Flask-Script</a></li> <li> <a href="https://github.com/lepture/flask-wtf" title="None" target="_blank">Flask-WTF</a></li> <li> <a href="https://github.com/mgood/flask-debugtoolbar" title="None" target="_blank">Flask-Debugtoolbar</a></li> </ul> <p>管理画面作るのにはFlask-Adminを使ってみた。Flask-Adminは結構更新されてて、時間が空くと互換性無くなってる時とかあって泣けた。 ドキュメントも微妙に古かったり詳しく書いてなかったりして、わからない時はソース読んだりすることにもなった(ある意味勉強的には良かった)。</p> <p><img src="/entry/logpot-publish/admin.png" alt="Flask-Admin" title="None"/> </p> <p>html側は結構Flask-Admin内のテンプレートを流用して改変する感じにしたら融通効かない感じになってまだデフォルトっぽいところから抜け出せず少し使いにくい管理画面になってる。逆に、慣れるとテンプレート的な画面ならすぐに作れるのはめちゃくちゃ楽。</p> <p>あとはMarkdownのレンダーにはmisakaを使い、RSSにはfeedgenを使ってみた。</p> <h2>タスクランナーにGulpを使う</h2> <p>Gruntを使っていたけどこの機会にそれをGulpに乗り換えた。一番やりたかったのは、再利用&amp;わかりやすいようにタスクごとのファイルに分けるのと、設定を1ファイルにまとめることだった。</p> <p>勉強にはこの記事群を最初から読んでいくのが一番分かりやすかった。</p> <ul> <li> <a href="http://qiita.com/advent-calendar/2014/gulpjs" title="None" target="_blank">これからはじめるGulp.js(全俺) Advent Calendar 2014 - Qiita</a></li> </ul> <p>特にこの記事に知りたかったことが書いてあったので、この記事を応用した形で利用させていただいた。</p> <ul> <li> <a href="http://whiskers.nukos.kitchen/2014/12/07/gulp-require-dir.html" title="None" target="_blank">これからはじめるGulp(7):require-dirモジュールを使ったタスク単位のファイル分割</a></li> </ul> <p>で、雛形として完成したのが付属物その1: <a href="https://github.com/moremorefor/gulp-bourbon-skeleton" title="None" target="_blank">moremorefor/gulp-bourbon-skeleton</a> </p> <p>その後色んなプロジェクトで調整しながら使っている。便利。</p> <p>今回のブログでは、static内だけをgulpで処理するように雛形をちょっとだけカスタマイズした。gulpコマンドはProcfileに書いておいて、ForemanのPythonクローン <a href="[nickstenning/honcho](https://github.com/nickstenning/honcho" title="None" target="_blank">honcho</a> を叩いてFlaskアプリと一緒に起動するようにしている。</p> <h2>Sassの設計</h2> <p>Sassのライブラリには前から <a href="http://bourbon.io/" title="None" target="_blank">Bourbon</a> を使っていて、Sassはそのサンプルで紹介されていた構成にして使っていたけど、そろそろ真面目にCSS設計を勉強しないとなと思って今回考えた。</p> <p>とりあえずこの本を読んで改めて基本を理解した。前後のページを行き来して見たい場面が多くてKindleで買ったのは失敗だった&hellip;。</p> <ul> <li> <a href="http://book.impress.co.jp/books/1113101128" title="None" target="_blank">Web制作者のためのCSS設計の教科書 モダンWeb開発に欠かせない「修正しやすいCSS」の設計手法 | インプレス</a></li> </ul> <p>で、結果的に <a href="https://github.com/hiloki/flocss" title="None" target="_blank">FLOCSS</a> がいいかなと思い、ちょうど別のプロジェクトもあったのでそっちで先に試してみた。</p> <p>が、だが書いてみるとめんどくさい。規模が大きくないプロジェクトにはこんなに細かい必要はないと思い直して、結果、このブログではディレクトリを4つのレイヤーに区切るだけにした。Class名についても自分なりのやり方をまだ検討中&hellip;。</p> <p>とりあえず今回は手を付けたということでOKとして、あとはMarkdownのサンプル一覧を用意して、それぞれの要素用のcssを <a href="/entry/example" title="None" target="_blank">作成した</a> 。</p> <p><img src="/entry/logpot-publish/markdown.png" alt="Markdown" title="None"/> </p> <h2>サーバーセットアップ</h2> <p>かなりわかっていることが少ないところから始まった。少しはやったことあったけどどっから手を付けたらいいのかわからない。ので、とりあえず手を動かさないと無理だなと思い、この2つの記事をベースに一通り手を動かしてみた。動かした内容はすべてメモしておいた。</p> <ul> <li> <a href="http://nekopunch.hatenablog.com/entry/2015/01/16/112402" title="None" target="_blank">はじめてでも爆速でCentOS6.6(さくらのVPS)をセキュアにセットアップする方法まとめ - 憂鬱な世界にネコパンチ!</a></li> <li> <a href="http://qiita.com/junki0605/items/6ce3df1933ef6d31ddfa" title="None" target="_blank">サーバー構築 - さくらVPSの初期設定とCentOSによるWEBサーバー環境構築まとめ - Qiita</a></li> </ul> <p>その後、そのメモの中から今回に必要な処理を書き出して &amp; 追加で調べていって(特にセキュリティ周りなど)、それをまとめた。</p> <ul> <li>epel.repoの追加</li> <li>ユーザーの作成</li> <li>etckeeperの導入</li> <li>authorized_keyの追加</li> <li>sshの設定</li> <li>rootログイン・パスワードログインの禁止</li> <li>iptablesの設定</li> <li>Nginxのインストール・設定</li> <li>などなど&hellip;</li> </ul> <p>だが初心者の自分がこれをこのままVPSとかに構築していっても<strong>いずれ絶対に失敗する</strong>ことが目に見えている。ので次の段階に進む。</p> <h2>Ansibleでその自動化 (+Vagrant)</h2> <p>失敗しても環境をいくらでも作り直し、ほぼ自動的に失敗した地点まで戻せるように、VagrantでCentOSの環境を作り、Ansibleのplaybookに処理を逐一書いていって、それを適用して試すという方策をとった。</p> <p>ということでまずはAnsibleの基本を勉強する。</p> <ul> <li> <a href="https://gumroad.com/l/TNHSc" title="None" target="_blank">入門 Ansible (PDF, EPUB, MOBI同梱)</a></li> <li> <a href="http://sechiro.hatenablog.com/entry/2015/01/06/Ansible%E3%82%92%E4%BD%BF%E3%81%84%E5%87%BA%E3%81%99%E5%89%8D%E3%81%AB%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%8B%E3%81%A3%E3%81%9F%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF" title="None" target="_blank">Ansibleを使い出す前に押さえておきたかったディレクトリ構成のベストプラクティス - 双六工場日誌</a></li> <li> <a href="https://github.com/ansible/ansible-examples" title="None" target="_blank">ansible/ansible-examples</a></li> </ul> <p>基本を抑えたところでどんどんplaybookに書いて適用して試していく。最初はmain.yml一個を用意してそこに全部書いていって、あとでベストプラクティスのRoleに分割していった。</p> <p>最終的にインストールしたのはこの辺</p> <ul> <li>Nginx</li> <li>nodebrew &amp; Node 0.12.7</li> <li>Python 3.4 &amp; virtualenv</li> <li>rbenv &amp; Ruby 2.2.2</li> <li>PostgreSQL 9.4</li> </ul> <p>このやり方、初心者的にはいつでも試していた時点に戻せる環境があるという心強さが一番ありがたかった。</p> <p>で完成したのが付属物その2: <a href="https://github.com/moremorefor/ansible-playbooks" title="None" target="_blank">moremorefor/ansible-playbooks</a> </p> <h4>問題</h4> <p>だがしかしハマりどころも多かった。</p> <ol> <li><p>まずVagrantと一緒にAnsibleを勉強しだしたので、上手くplaybookが適用されない時に、ssh周りの設定で詰まることが多かった。</p></li> <li><p>次に、未だにわかってないのが、本当に最初からVagrant上にplaybookを適用すると、sshの設定をした後で当たり前だが繋がらなくなる。ので全部で</p> <div class="highlight"><pre><span class="nv">$ </span>vagrant up <span class="nv">$ </span>vagrant ssh-config &gt; ssh.config <span class="nv">$ </span>ansible-playbook -i hosts setup.yml (一度目) ・vagrantfileのsshの設定を変更 ・private_keyを削除 <span class="nv">$ </span>vagrant reload <span class="nv">$ </span>vagrant ssh-config &gt;! ssh.config <span class="nv">$ </span>ansible-playbook -i hosts app.yml (二度目) </pre></div> <p>という手順を踏まないといけなくなる。めんどくさい。これ普通どうしてるんだろう?</p></li> <li><p>最後に、Vagrant上のCentOSに、iptablesの設定でプライベートIPアドレスを弾く設定をすると、設定後、Vagrantにsshが通らなくなる。今となってはなるほどという感じだけど&hellip;。</p></li> </ol> <h2>アプリケーションサーバー</h2> <p>最後にアプリをデプロイするに辺り、アプリケーションサーバーをどうするかという問題に当たった。例に違わずとりあえず参考になりそうな記事を元に手を動かす。</p> <ul> <li> <a href="https://www.digitalocean.com/community/tutorials/how-to-deploy-flask-web-applications-using-uwsgi-behind-nginx-on-centos-6-4" title="None" target="_blank">How To Deploy Flask Web Applications Using uWSGI Behind Nginx on CentOS 6.4 | DigitalOcean</a></li> </ul> <p>これをやってみてuWSGI+Nginxはわかってきたが、Gunicornが気になったのと、もしエラーなどでアプリが落ちた時の死活監視を考えないといけないことに気づきSupervisorを試してみた。</p> <ul> <li> <a href="http://blog.shun-ichiro.com/howto/nginx-gunicorn-supervisor-flask/" title="None" target="_blank">nginx/gunicorn/supervisorでflaskアプリを動かす | かねしろぐ - 兼城駿一郎(@pinkroot )のライフログ</a></li> </ul> <p>結果、Gunicornが良さそうだったので乗り換えたのと、Python3.4だとSupervisorが上手く動かなかった&hellip;。調べた結果、代わりに <a href="https://circus.readthedocs.org/en/latest/" title="None" target="_blank">Circus</a> が良さそうということで、最終的にCircus+Gunicorn+Nginxで行くことにした。静的ファイルはNginxで返して、ソケット通信でGunicornとやり取りしてる。</p> <p><img src="/entry/logpot-publish/mackerel.png" alt="Mackerel" title="None"/> あとは、監視ツールとしてMackerelを入れてSlackと連携し、とりあえずOKということにした。デプロイはAnsibleでやったけど、結局まだ手動でやらないといけないことも残っているので、今後はデプロイの自動化を考えないといけない。</p> <h2>まとめ</h2> <p>ちまちまと色々勉強してきた。勉強した結果、このブログの他に、Photoshopと連携する各種自作ツールなどを自分でサーバーに置いて使えるようになって、仕事の効率がかなりアップしたりしている。良い。(注:一応ある程度セキュリティにも気をつけてる)</p> <p>まだ、カテゴリページ作ったり、DBの定期バックアップするとかやらないといけないことが残っているので、ちまちま作りながらこのブログも更新していきたいと思う。</p> Python Sun, 03 Jan 2016 22:04:28 +0900 Example article http://log.moremorefor.net/entry/example <h1>Headline</h1> <p>Curabitur blandit tempus porttitor. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec sed odio dui. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Maecenas sed diam eget risus varius blandit sit amet non magna. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p> <h2>Headline2</h2> <p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Etiam porta sem malesuada magna mollis euismod. Maecenas faucibus mollis interdum. Vestibulum id ligula porta felis euismod semper.</p> <h3>Headline3</h3> <p>Etiam porta sem malesuada magna mollis euismod. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Maecenas faucibus mollis interdum. Nullam quis risus eget urna mollis ornare vel eu leo.</p> <h4>Headline4</h4> <p>Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Integer posuere erat a ante venenatis dapibus posuere velit aliquet.</p> <h5>Headline5</h5> <p>Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p> <h6>Headline6</h6> <p>Maecenas sed diam eget risus varius blandit sit amet non magna. Etiam porta sem malesuada magna mollis euismod.</p> <h3>Another Elements</h3> <p>Leave 2 spaces at the end of a line to do a line break.</p> <p>Text attributes <em>italic</em>, <strong>bold</strong>,<code>monospace</code>, <del>strikethrough</del>.</p> <p>Unordered list:</p> <ul> <li>Red</li> <li>Green</li> <li>Blue</li> </ul> <p>Numbered list:</p> <ol> <li>apples</li> <li>oranges</li> <li>pears</li> </ol> <p>Definition list:</p> <dl> <dt>Coffee</dt><dd>Black hot drink</dd> <dt>Milk</dt><dd>White cold drink</dd> </dl> <div class="highlight"><pre><span class="k">def</span> <span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="p">):</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span> <span class="k">while</span> <span class="n">a</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">:</span> <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s">&#39; &#39;</span><span class="p">)</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="n">b</span> <span class="k">print</span><span class="p">()</span> <span class="n">fib</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span> </pre></div> <!-- dummy comment line for breaking list --> <blockquote> <p>This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.</p> <p>Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse id sem consectetuer libero luctus adipiscing.</p> </blockquote> <p><a href="https://www.wikipedia.org/" title="Link Title" target="_blank">Wikipedia</a> </p> <p><a href="http://google.co.jp" title="Link Title" target="_blank">Google</a> </p> <p><a href="http://www.yahoo.co.jp" title="Link Title" target="_blank">Yahoo</a> </p> <hr> <p>horizontal rule</p> <hr> <p>horizontal rule</p> <hr> <p>horizontal rule</p> <hr> <p>horizontal rule</p> <hr> Python Sun, 03 Jan 2016 21:05:06 +0900