golang : 日本語(マルチバイト)文字を含む string の substring
go では string のスライスは byte として扱われるので、日本語のようにマルチバイト文字を含んだ文字列 str に対して str[start:start+length]
のようなことをすると、思わぬ場所が切り取られてしまいます。
この問題を回避するために、一旦 rune にキャストしてから string に戻します。
func substring(str string, start, length int) string { if start < 0 || length <= 0 { // 明らかに不正な値なので、チェックせずに進んで panic を起こしても良さそうです。 return str } r := []rune(str) if start + length > len(r) { return string(r[start:]) } else { return string(r[start:start + length]) } }
TypeScript : typings による Chrome Extension 用型定義のインストール
typings で型定義ファイルの管理を行うので、未インストールの場合はインストールします。
npm install -g typings
拡張機能のプロジェクトのディレクトリに移動し、typings init
コマンドで初期化します(typings.json ファイルが作成されます)。 その後、install コマンドで Chrome Extension 用の 型定義ファイル(.d.ts)をインストールします。
typings install chrome --ambient --save typings install filesystem --ambient --save typings install filewriter --ambient --save typings install webrtc/mediastream --ambient --save typings install es6-shim --ambient --save
chrome が Chrome Extension 用の型定義の本体ですが、これをインストールするだけ使えず、chrome が依存している他の型定義もインストールする必要があります。 typings でインストールしたときに、Stripped reference というメッセージが表示された場合、それらを手動でインストールする、と覚えておけば良さそうです。
> typings install chrome --ambient --save typings INFO reference Stripped reference "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/7de6c3dd94feaeb21f20054b9f30d5dabc5efabd/webrtc/MediaStream.d.ts" during installation from "chrome" typings INFO reference Stripped reference "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/7de6c3dd94feaeb21f20054b9f30d5dabc5efabd/filesystem/filesystem.d.ts" during installation from "chrome" chrome └── (No dependencies)
--ambient って何者?など typings についてより詳しく知りたい場合は TypeScriptの型定義管理ツールTypingsについて - Qiita が参考になります。
Git : コミットメッセージに自動でブランチ名を挿入する
参考:How to add Git's branch name to the commit message?
- .git/hooks/ 下にある prepare-commit-msg.sample を prepare-commit-msg に変更する(.sample を外す)
- prepare-commit-msg に以下のようなスクリプトを追記する
branchPath=$(git symbolic-ref -q HEAD) # branchPath は refs/heads/feature/XXXX_YYYY のような文字列に branchName=${branchPath##*/} # 最後の / 以下を取得し、branchName は XXXX_YYYY のような文字列に issueNumber=$(echo $branchName | cut -d "_" -f 1) # "_" を delimiter として cut し、issueNumber は XXXX に firstLine=$(head -n1 $1) if [ -z "$firstLine" ] ;then # 最初の行が空行かチェックして、amend でないことを確認 sed -i "1s/^/($issueNumber) \n/" $1 # コミットメッセージの先頭に (XXXX) という文字列でブランチの情報を追加。 fi
参考先に少し修正を加え、branchName を直接使うのではなく、cut を使ってその一部を使うようにしています。
例えば feature/XXXX_YYYY
というブランチ名だった場合、コミットメッセージには (XXXX) という形でブランチ名の一部が入るようになります。
これは、自分は XXXX の部分にイシューやタスクの番号を、YYYY の部分に少し説明的な文章を入れる形でブランチ名を作っているためです。
Unreal Engine : Timeline を C++ コードで作成・実行する
手順
準備
- Timeline で使用する Curve を「Content Browser を右クリック」→「Miscellaneous」→「Curve」(もしくは「Float Curve」)で作成する
- 作成した Curve を右クリックして「Copy Reference」する
- C++ のコード上で ConstructorHelpers::FObjectFinder を使い、先ほど作成した Curve を取得する
- FTimeline オブジェクトを作成する
- FTimeline オブジェクトに追加する FOnTimeline* (FOnTimelineVector や FOnTimelineFloat など Curve の種類による)を作成する
- FOnTimeline* に、Timeline が更新される毎に呼び出す関数を設定する
- FTimeline に、Curve と FOnTimeline* を追加する
Timeline 完了時のイベントを追加する場合のために SetTimelineFinishedFunc などもあるので、適宜使用する。
実行
- FTimeLine の PlayFromStart 関数を呼ぶ
- 途中から再生する場合は Play、逆再生する場合は Reverse など再生開始方法は任意
- Tick で FTimeline の IsPlaying() が真であれば、TickTimeline(DeltaTime) を呼ぶ
- 更新頻度が低くて良い場合は Tick ではなく TickTimeline を呼ぶだけの関数を設定した Timer を作成したほうが負荷が軽くなって良いかも
サンプルコード
void MyActor::MyActor() { // 他の初期化処理... // メンバー変数として FTimeline* MyTimeline を定義している MyTimeline = new FTimeline(); MyTimeline->SetTimelineLength(1.0f); // 作成した Timeline の取得。Copy Reference でコピーしたテキストを TEXT の中に貼り付ける。 // <> の中身は Curve の種類によって変更する。今回は Vector。 const ConstructorHelpers::FObjectFinder<UCurveVector> StepCurve(TEXT("CurveVector'/Game/Timeline/TimelineCurve.TimelineCurve'")); // Timeline 更新時に呼ばれる関数の設定。このクラスに定義している void TimelineStep(FVector v) を呼ぶ。 FOnTimelineVector MyTimelineStepFunction; MyTimelineStepFunction.BindUFunction(this, "TimelineStep"); MyTimeline->AddInterpVector(StepCurve.Object, MyTimelineStepFunction); // Timeline 終了時に呼ばれる関数の設定。このクラスに定義している void TimelineFinished(FVector v) を呼ぶ。 FOnTimelineEvent MyTimelineFinishedFunc; MyTimelineFinishedFunc.BindUFunction(this, "TimelineFinished"); MyTimeline->SetTimelineFinishedFunc(MyTimelineFinishedFunc); } void MyActor::BeginPlay() { if (MyTimeline != nullptr) { MyTimeline->PlayFromStart(); } } void MyActor::Tick( float DeltaTime ) { Super::Tick( DeltaTime ); // Timeline 再生中であれば DeltaTime 進めて実行 if (MyTimeline != nullptr && MyTimeline->IsPlaying()) { MyTimeline->TickTimeline(DeltaTime); } } // TickTimeline 毎に、進んだ Time の合計と対応した Timeline から得られる値でこの関数が呼ばれる // .h で定義する際に UFUNCTION() を付けておくこと void MyActor::TimelineStep(FVector value) { UE_LOG(LogTemp, Warning, TEXT("TimelineStep : (%.2f, %.2f, %.2f)"), value.X, value.Y, value.Z); } // Timeline 完了時に呼ばれる関数 // .h で定義する際に UFUNCTION() を付けておくこと void MyActor::TimelineFinished() { UE_LOG(LogTemp, Warning, TEXT("TimelineStep Finished")); }
参考
Blueprint も良くできていると思いますが、メインは C++ で書いたほうが楽そうです。
Unreal Engine 4で極めるゲーム開発:サンプルデータと動画で学ぶUE4ゲーム制作プロジェクト
- 作者: 湊和久,堀越祐樹
- 出版社/メーカー: ボーンデジタル
- 発売日: 2015/07/25
- メディア: 大型本
- この商品を含むブログ (1件) を見る
WPF/XAML : DataGrid の行にコンテクストメニューを設定する
方針・ポイント
- EventSetter を使って DataGridRow に右マウスボタンイベント(MouseRightButtonUp)を設定する
- ContextMenu を DataGrid.Resources 内で作る
- そのイベント内で、Resources の ContextMenu を取得、設定する
ContextMenu の方もコード上で作る、右クリック時ではなく行を追加した時に ContextMenu を設定するなど、他にも様々な方法で同じことが実現できると思いますが、今回は上記の方法で行います。
右マウスボタンのイベントの方が、右クリックによるコンテクストメニューの表示よりも先に行われるようなので、最初の右クリックでメニューは表示されます。
サンプルコード
XAML
<DataGrid x:Name="MyDataGrid" AutoGenerateColumns="False"> <DataGrid.Resources> <!-- ContextMenu の作成 --> <ContextMenu x:Key="DataGridContextMenu"> <MenuItem Header="Menu 1" Click="MyDataGrid_ContextMenu1_Click"/> <MenuItem Header="Menu 2" Click="MyDataGrid_ContextMenu2_Click"/> </ContextMenu> <!-- DataGridRow に右マウスボタンイベントの設定 --> <Style TargetType="{x:Type DataGridRow}"> <EventSetter Event="MouseRightButtonUp" Handler="MyDataGrid_Row_MouseRightButtonUp"/> </Style> </DataGrid.Resources> <!-- 適当なサンプルデータ表示用の列 --> <DataGrid.Columns> <DataGridTextColumn Header="苗字" Binding="{Binding FamilyName}" Width="80"/> <DataGridTextColumn Header="名前" Binding="{Binding FirstName}" Width="80" /> </DataGrid.Columns> </DataGrid>
C#
public partial class MainWindow : Window { // 適当なサンプルデータ用のクラス public class Person { public string FirstName { get; set; } public string FamilyName { get; set; } public Person(string firstName, string familyName) { FirstName = firstName; FamilyName = familyName; } } private ObservableCollection<Person> MyDataGrid_SourceCollection; public MainWindow() { InitializeComponent(); // 適当サンプルデータを追加 MyDataGrid_SourceCollection = new ObservableCollection<Person>(); MyDataGrid_SourceCollection.Add(new Person("太郎", "山田")); MyDataGrid_SourceCollection.Add(new Person("花子", "佐藤")); MyDataGrid.ItemsSource = MyDataGrid_SourceCollection; } // DataGridRow に対する右マウスボタンイベント private void MyDataGrid_Row_MouseRightButtonUp(object sender, MouseButtonEventArgs e) { // Resources から ContextMenu を取得して設定 (sender as DataGridRow).ContextMenu = MyDataGrid.Resources["DataGridContextMenu"] as ContextMenu; } // ContextMenu の MenuItem のイベントその1 private void MyDataGrid_ContextMenu1_Click(object sender, EventArgs e) { if (MyDataGrid.SelectedItem != null) { MessageBox.Show("Menu 1 : FirstName = " +(MyDataGrid.SelectedItem as Person).FirstName); } } // ContextMenu の MenuItem のイベントその2 private void MyDataGrid_ContextMenu2_Click(object sender, EventArgs e) { if (MyDataGrid.SelectedItem != null) { MessageBox.Show("Menu 2 : FamilyName = " + (MyDataGrid.SelectedItem as Person).FamilyName); } } }
Markdown : タイトル末尾に # 記号を使う
Markdown で # を使った形式でタイトルを書く時、
### C#
と書くと結果は
C
となり、末尾の #(ハッシュ記号?シャープ記号?)が表示されません。
以下のように、後ろに # をつけることできちんと表示されるようになります。
### C# #
C#
Unreal Engine : C++ クラスを削除する
- Visual Studio 上で削除対象のクラスの .h と .cpp を削除します
- Visual Stdio 2015 の Remove ではプロジェクトから削除するだけのようなので、エクスプローラーを開きファイルの実体も削除しておきます
- Visual Studio 上でソリューションをビルドします
- このタイミングでの Unreal Engine のエディタからのコンパイルは、先ほど削除したファイルが見つからない、というエラーで失敗しました
- Unreal Engine を一旦終了し、再度開きます
- Content Browser でクラスが消えていることを確認します
Content Browser からは削除やリネームができないんですね。
使っていないクラスを消すくらいならば大した問題はなさそうですが、クラスを継承した Blueprint が存在したりする場合や、削除ではなくクラス名の変更をする場合などはいろいろとややこしくなりそうです。