i++

プログラム系のメモ書きなど

WPF/XAML : DataGrid の行にコンテクストメニューを設定する

方針・ポイント

  • EventSetter を使って DataGridRow に右マウスボタンイベント(MouseRightButtonUp)を設定する
  • ContextMenu を DataGrid.Resources 内で作る
  • そのイベント内で、Resources の ContextMenu を取得、設定する

ContextMenu の方もコード上で作る、右クリック時ではなく行を追加した時に ContextMenu を設定するなど、他にも様々な方法で同じことが実現できると思いますが、今回は上記の方法で行います。

右マウスボタンのイベントの方が、右クリックによるコンテクストメニューの表示よりも先に行われるようなので、最初の右クリックでメニューは表示されます。

f:id:tkyjhr:20160127145816p:plain

サンプルコード

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);
        }
    }
}

Unreal Engine : C++ クラスを削除する

  1. Visual Studio 上で削除対象のクラスの .h と .cpp を削除します
    • Visual Stdio 2015 の Remove ではプロジェクトから削除するだけのようなので、エクスプローラーを開きファイルの実体も削除しておきます
  2. Visual Studio 上でソリューションをビルドします
    • このタイミングでの Unreal Engine のエディタからのコンパイルは、先ほど削除したファイルが見つからない、というエラーで失敗しました
  3. Unreal Engine を一旦終了し、再度開きます
  4. Content Browser でクラスが消えていることを確認します

Content Browser からは削除やリネームができないんですね。

使っていないクラスを消すくらいならば大した問題はなさそうですが、クラスを継承した Blueprint が存在したりする場合や、削除ではなくクラス名の変更をする場合などはいろいろとややこしくなりそうです。

参考

Unreal Engine : C/C++ コードからのログ出力

コンソール(Output Log)へのログ出力と、ゲーム画面上へのログ出力の2通りの方法でログを確認できます。

Console ログ出力

UE_LOG(カテゴリ名, ログレベル, テキストフォーマット, テキスト引数) を使用します。

カテゴリなし
// LogTemp は定義なしで使用可能なカテゴリです
UE_LOG(LogTemp, Warning, TEXT("%s: Hello!"), __FUNCTIONW__);
単一ファイル用カテゴリ
// このカテゴリを使う .cpp 内で定義します
// カテゴリ名を "(ダブルクオーテーション)で囲んで文字列として定義する必要はありません
DEFINE_LOG_CATEGORY_STATIC(LogCategoryName, Warning, All);

UE_LOG(LogCategoryName, Warning, TEXT("%s: Hello!"), __FUNCTIONW__);
複数ファイル用カテゴリ
// (プロジェクト名).h に書きます
DECLARE_LOG_CATEGORY_EXTERN(LogCategoryName, Warning, All);

// (プロジェクト名).cpp に書きます
DEFINE_LOG_CATEGORY(LogCategoryName);

// ログを出すところで
UE_LOG(LogCategoryName, Warning, TEXT("%s: Hello!"), __FUNCTIONW__);
ログレベルの種類
レベル 備考
Fatal コンソールにログを出力すると同時にゲームをクラッシュさせます
(試しにコンストラクタに書いてみたらエディタの方がクラッシュしました…)
Error ログテキストは赤色
Warning ログテキストは黄
Display ログテキストは灰色
Log Log 以下のレベルのメッセージはコンソールには出力されず、ログファイルにのみ記録されます
(とドキュメントからは読み取れますが、自分の環境では Log までは Output Log に出力され、Verbose 以下から表示が消えました)
Verbose
VeryVerbose
All 実態は VeryVerbose です(All = VeryVerbose と定義されています)

画面ログ出力

GEngine->AddOnScreenDebugMessage(id, 表示時間, テキスト色, 表示するテキスト) を使用します。
GEngine は利用できない可能性があるので、AddOnScreenDebugMessage を呼び出す前にその有無をチェックする必要があります。マクロを書いておくと楽です。

#include "EngineGlobals.h"
#include "Runtime/Engine/Classes/Engine/Engine.h"

// 第1引数に -1 以外の数値を渡すと、前にその数値を使って出力したログを上書きします。-1 の場合は常に上書きせずログが追加されます。
// 第2引数は表示する時間(秒)
#define DISPLAY_LOG(fmt, ...) if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT(fmt), __VA_ARGS__));

DISPLAY_LOG("%s: Hello at line %d", __FUNCTIONW__, __LINE__);

参考

Unreal Engine : Blueprint/UserWidget.h が Visual Studio で認識されない

  1. (プロジェクト).Build.cs ファイルに UMG を使うための依存関係を設定する
  2. 一度 Visual Studio を閉じ、エクスプローラーで .uproject ファイルを選択して右クリックメニューから "Generate Visual Studio project files" 選択する

これで Visual Studio のソリューションファイルが更新され、Blueprint/UserWidget.h が開けるようになり、 intellisense による UUserWidget などに対する補完も効くようになります。

f:id:tkyjhr:20151212174645p:plain

// UMG を使う際に Games/(Project)/Source/(Project).Build.cs に必要な設定。Public の "UMG" と、Private の "Slate", "SlateCore"。
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "UMG" });
PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });

参考

Unreal Engine : Starter Content を後から追加する

  1. Content Browser の Add New ボタン(左上緑色)を押して Add Feature or Content Pack を選択
  2. Content Packs タブから Starter Content を選択して Add to Project ボタンを押す

新規プロジェクト作成時のテンプレートとして使用できる他プロジェクトの Blueprint や C++ のコードも、Add Feature or Content Pack から追加可能。

Unreal Engine : C++ プロジェクトの作成でエラー

Common Tools for Visual C++ 2015 がインストールされていないせいでした。そういえば、Visual Studio 2015 はデフォルトでは C++ が入っていないんでしたね。

Visual Studio 2015 を Unreal Engine で使用するために必要な設定は以下のとおりです。

  1. 無料開発ツール - Visual Studio Community 2015 から Visual Studio 2015 Community をダウンロードします
  2. 自分の場合はすでに一部はインストール済みだったので Update を選択(次のダイアログが出てくるまで結構時間がかかりました)
  3. Update 終了後に出てくるダイアログで Modify を選択します
  4. インストールする機能を選択できるので、Programming Languages -> Visal C++ -> Common Tools for Visual C++ 2015 にチェックを入れて Next、Update と進みます
  5. 完了後 は PC の再起動が必要です。再起動後、Unreal EngineC++ のプロジェクトが作成できるようになります

ちなみに最初に出たエラーメッセージの内容は以下の通り。

Running C:/Program Files/Epic Games/4.10/Engine/Binaries/DotNET/UnrealBuildTool.exe  -projectfiles -project="E:/Project/UnrealEngine/BatteryController/BatteryController.uproject" -game -rocket -progress -2015
Visual C++ 2015 toolchain does not appear to be correctly installed. Please verify that "Common Tools for Visual C++ 2015" was selected when installing Visual Studio 2015.
Discovering modules, targets and source code for game...
UnrealBuildTool Exception: ERROR: Failed to find cl.exe in the default toolchain directory C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\../../VC/bin/amd64\cl.exe. Please verify that "Common Tools for Visual C++ 2015" was selected when installing Visual Studio 2015.

参考