Search
Categories
Articles
Rainmeter関連
ファイル置き場
お知り合いなど

スポンサーサイト

--.--.-- | スポンサー広告

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

RainmeterのROUNDLINE

2009.03.03 | Rainmeter-dev

0 Comments

以前から、システム情報やfoobar2000での再生曲情報を表示させるのに、Rainmeterを使ってます。
GUIで設定できるらしいSamurizeとは違い、ファイルを直接いじってスキンの表示内容を設定していくタイプですが、トリッキーなことをしなければ編集は比較的楽だと思います。でも、WebParserを使って正規表現をごりごり書くようなのは無理w

一度スキンの設定をいじり始めると、「ここ気になる」「こっちのほうが」「いややっぱ元のほうが」なんてことになるので、なかなか止まらなくて困ります。凝った画像類を用意できないから、いじるとしても、ほとんど標準機能だけで表示できる文字やグラフばかりですけどね。

で、最近気づいたこと。
Meter=ROUNDLINEって、Solid=1を指定すれば塗りつぶした円弧を描けたどころか、クリップまでできたのね……。
名前だけ見て、そういうことはできないって思ってました。線描くだけなのかと。やはり、動作を知るにはヘルプや公開スキンを参考にするだけでなく、Rainmeter本体のソースも参考にしろってことですね。わかります。

恵まれたことに、Rainmeterのソースはこちらで公開されていますし。
最近、Google Codeにもアップされたようで、今後の展開にも期待しています。英語さっぱりなんで見てるだけですが……。

というわけで以下は備忘録的に。

[ MeterRoundLine.cpp: line 135 - 148 ]

    if (m_Solid)
    {
        if (m_LineStart > 0.0)
        {
            // Create clipping region
            GraphicsPath path;
            path.AddEllipse(REAL(cx - m_LineStart), REAL(cy - m_LineStart), REAL(m_LineStart * 2), REAL(m_LineStart * 2));
            graphics.SetClip(&path, CombineModeExclude);
        }
 
        // Calculate the center of for the line
        SolidBrush solidBrush(m_LineColor);
        graphics.FillPie(&solidBrush, (REAL)(cx - m_LineLength), (REAL)(cy - m_LineLength), (REAL)(m_LineLength * 2.0), (REAL)(m_LineLength * 2.0), (REAL)(m_StartAngle * 180.0 / PI), (REAL)(m_RotationAngle * m_Value * 180.0 / PI));
    }


コードを見るとこんな感じになってます。
でも、これだと円弧をクリップした部分だけアンチエイリアスが効かなくてギザギザになるんですよね。同じようなことをやろうとして、同じようなコードを書いてたので、どうしたものか悩ましかったというか。

実際に表示させてみるとこんな感じに。スキンはdeviantARTから「HUD arcs」というのを借りてきました。
リンク先にも表示例がありますけど、よくこんな複雑そうなの作れるなぁとw

20090302_Rainmeter_HUD_arcs

やはり円形にクリップした境界部分にはアンチエイリアスがかからず、ギザギザになってます。

GraphicsPathを使ったクリップでもRegionを使ったクリップでも同じようにかかってくれないので、GDI+の仕様なんでしょうかね。
GDI+に限らなければ他のやり方もあるんでしょうけど……そっちは全然知らないので、GDI+で少し足掻いてみることに。結論としては、「クリップして削られた境界部分だけ、クリップし直して円弧を描き足す」処理を追加してみました。

[ MeterRoundLine.cpp (Modified): line 135 - 166 ]

    if (m_Solid)
    {
        if (m_LineStart > 0.0)
        {
            // Create clipping region
            RectF clipRect(REAL(cx - m_LineStart), REAL(cy - m_LineStart), REAL(m_LineStart * 2), REAL(m_LineStart * 2));
 
            GraphicsPath path;
            path.AddEllipse(clipRect);
            graphics.SetClip(&path, CombineModeExclude);
 
            // Calculate the center of for the line
            REAL startAngle = (REAL)(m_StartAngle * 180.0 / PI);
            REAL sweepAngle = (REAL)(m_RotationAngle * m_Value * 180.0 / PI);
            SolidBrush solidBrush(m_LineColor);
            graphics.FillPie(&solidBrush, (REAL)(cx - m_LineLength), (REAL)(cy - m_LineLength), (REAL)(m_LineLength * 2.0), (REAL)(m_LineLength * 2.0), startAngle, sweepAngle);
 
            if (m_AntiAlias)
            {
                //fix aliasing problem
                Pen fixPen(m_LineColor, 1.0f);
                graphics.SetClip(&path, CombineModeReplace);
                graphics.DrawArc(&fixPen, clipRect, startAngle, sweepAngle);
            }
        }
        else
        {
            // Calculate the center of for the line
            SolidBrush solidBrush(m_LineColor);
            graphics.FillPie(&solidBrush, (REAL)(cx - m_LineLength), (REAL)(cy - m_LineLength), (REAL)(m_LineLength * 2.0), (REAL)(m_LineLength * 2.0), (REAL)(m_StartAngle * 180.0 / PI), (REAL)(m_RotationAngle * m_Value * 180.0 / PI));
        }
    }


クリップしたい円形の領域をSetClipして、FillPieするまでは同じ。その後、クリップしていた領域を逆にセットし直して円弧を描いてます。
 ・144行目のクリップでは、円形の領域を除いた領域を描画領域に設定(CombineModeExclude)
 ・156行目のクリップでは、円形の領域を描画領域に設定(CombineModeReplace)

他に賢いやり方があるのかもしれないし、線の太さとかも考えたほうがいいのかもしれないけど、とりあえず自分の意図したように動いている(ように見える)ので、よしかなと。
上のスキンで再度試すとこんな感じに。

20090302_Rainmeter_HUD_arcs_fix

多彩なRainmeterのスキンを数多く作られているsk2さん作の「MKG ver.sk2」でも試してみたので、ぺたり(左が適用前、右が適用後)。
sk2さんのスキンは他だと「Pixel L」をメインにちょこちょこ改造して使わせて貰ってます。ありがとうございます。

20090302_Rainmeter_MKG 20090302_Rainmeter_MKG_fix

今年は本体にも進展があったし、新しいプラグインも出てきているし(taskさん作のWMP/Winamp/iTunes/Foobar用Pluginなど。Foobar用を使わせて貰ってます)。Rainmeterはまだまだまだまだ楽しめそうですね。

<追記>
上記で、自分なりの変更を書いてみましたが、本家にも早速違う方法で修正が入ったようです。
r20での修正では、クリップしてから扇を描く(FillPie)本来の方法ではなく、円弧自体を太くして描く(DrawArc)方法を取っています。

この方法だと、開始位置と終了位置が微妙にズレます。前回と同じようにHUD arcsで試すと分かりやすいです。

20090313_Rainmeter_HUD_arcs_r20

DrawArc()で描くと、どうやらPenの太さが太くなるほど傾きやすい(?)ようで、部分部分で隣り合うものと重なり、くっ付いてしまってるのが分かります。
それが嫌で、いろいろと試行錯誤して前回のような形に落ち着いていたのですが、どうやらr21で綺麗に解決されたみたいですね。

20090313_Rainmeter_HUD_arcs_r21

内側と外側の2つの円弧を描き、その終端同士を直線で結んで閉じ、中を塗りつぶすとできあがり。……たぶん(sin,cosが理解できない頭なので)。
考えてみれば単純です。GraphicsPathを使えば簡単にできるのに、思い至らなかったなぁ。

« Rainmeter 0.14.1 SyntaxHighlighterテスト »

- Comments
0 Comments

管理者にだけ表示を許可する
- Trackbacks
0 Trackbacks


この記事にトラックバックする(FC2ブログユーザー)

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。