Irrlicht-0.11

Irrlicht0.11: Irrlicht.NET in Form

Irrlicht.NETで描画領域をSystem.Windows.Forms.Controlの中に作れるようになってる。HandleをIrrlichtDeviceのコンストラクタで渡すことで。これによって描画画面の上にTextBoxを置いたりも可能。

namespace IrrlichtInForm {
  using System;
  using System.Windows.Forms;
  using Irrlicht;
  using Irrlicht.Core;
  using Irrlicht.GUI;
  using Irrlicht.Video;
  using Irrlicht.Scene;
  using Irrlicht.IO;
  
  class Viewer: IEventReceiver {
    private Control control;
    private IrrlichtDevice device;
    private ICameraSceneNode camera;
    private IAnimatedMeshSceneNode controlNode;
    private ISceneNode targetNode;
    private MD2AnimationType controlNodeState = MD2AnimationType.STAND;
    private bool go;
    private bool back;
    private bool left;
    private bool right;
    
    public Viewer(int x, int y, int width, int height) {
      this.control = new Control();
      control.SetBounds(x, y, width, height);
      this.device = this.CreateDevice(control);
    }
    
    public ICameraSceneNode Camera {
      get { return camera; }
    }
    
    public Control Control {
      get { return control; }
    }
    
    public IFileSystem FileSystem {
      get { return device.FileSystem; }
    }
    public ISceneManager SceneManager {
      get { return device.SceneManager; }
    }
    
    public IGUIEnvironment Gui {
      get { return device.GUIEnvironment; }
    }
    
    
    public IAnimatedMeshSceneNode ControlNode {
      get { return controlNode; }
      set {
        if (targetNode != null) {
          targetNode.Remove();
          targetNode = null;
        }
        controlNode = value;
        if (value != null) {
          controlNode.SetMD2Animation(controlNodeState);
          targetNode = device.SceneManager.AddEmptySceneNode(controlNode, -1);
          targetNode.Position = new Vector3D(1, 0, 0);
        }
      }
    }
    
    private IrrlichtDevice CreateDevice(Control control) {
      DriverType driverType = DriverType.DIRECTX9;
      Dimension2D size = new Dimension2D(control.Width, control.Height);
      int bitDepth = 32;
      bool fullScreen = false;
      bool stencilBuffer = false;
      bool vsync = true;
      //bool antialias = true; // だめ
      bool antialias = false;
      IntPtr handle = control.Handle;
      
      IrrlichtDevice device = new IrrlichtDevice(
        driverType, size, bitDepth, fullScreen,
        stencilBuffer, vsync, antialias, handle);
      
      device.ResizeAble = true;
      device.EventReceiver = this;
      return device;
    }
    
    public IAnimatedMeshSceneNode LoadObject(string meshFile, string textureFile) {
      IAnimatedMesh mesh = device.SceneManager.GetMesh(meshFile);
      IAnimatedMeshSceneNode node = device.SceneManager.AddAnimatedMeshSceneNode(mesh, null, -1);
      node.SetMaterialFlag(MaterialFlag.LIGHTING, false);
      node.SetMaterialTexture(0, device.VideoDriver.GetTexture(textureFile));
      node.SetMD2Animation(MD2AnimationType.STAND);
      return node;
    }
    
    public ISceneNode LoadMap(string meshFile, Vector3D position) {
      IAnimatedMesh mesh = device.SceneManager.GetMesh(meshFile);
      ISceneNode node = device.SceneManager.AddOctTreeSceneNode(mesh, null, -1);
      node.SetMaterialFlag(MaterialFlag.LIGHTING, false);
      node.Position = position;
      return node;
    }
    
    public void AttachCamera(IAnimatedMeshSceneNode node) {
      ICameraSceneNode camera = device.SceneManager.AddCameraSceneNode(node, new Vector3D(-50, 10, 0),
                                                                       new Vector3D(0, 10, 0), -1);
      this.camera = camera;
    }
    
    public void Run() {
      while (device.Run() & control.Created) {
        ChangeControlNode();
        device.VideoDriver.BeginScene(true, true, new Irrlicht.Video.Color(0, 100, 100, 100));
        device.SceneManager.DrawAll();
        device.GUIEnvironment.DrawAll();
        device.VideoDriver.EndScene();
      }
    }
    
    private void ChangeControlNode() {
      if (go) {
        ChangeState(MD2AnimationType.RUN);
        Vector3D direction = targetNode.AbsolutePosition - controlNode.AbsolutePosition;
        float offset = back ? -1 : 5;
        Vector3D diff = direction * offset;
        Vector3D newPos = new Vector3D(diff.X + controlNode.Position.X,
                                       diff.Y + controlNode.Position.Y,
                                       diff.Z + controlNode.Position.Z);
        controlNode.Position = newPos;
        camera.Target = newPos;
      } else {
        ChangeState(MD2AnimationType.STAND);
      }
      if (left) {
        Vector3D rot = controlNode.Rotation;
        rot.Y -= 2f;
        controlNode.Rotation = rot;
      }
      if (right) {
        Vector3D rot = controlNode.Rotation;
        rot.Y += 2f;
        controlNode.Rotation = rot;
      }
    }
    
    bool IEventReceiver.OnEvent(Event ev) {
      if (ev.Type == EventType.MouseInput) {
        control.Focus();
      }
      if (ev.Type == EventType.KeyInput) {
        switch (ev.Key) {
        case (int) Keys.Up:
          go = ev.KeyPressedDown;
          break;
        case (int) Keys.Down:
          go = back = ev.KeyPressedDown;
          break;
        case (int) Keys.Left:
          left = ev.KeyPressedDown;
          break;
        case (int) Keys.Right:
          right = ev.KeyPressedDown;
          break;
        case (int) Keys.Q:
          if (!ev.KeyPressedDown && ev.KeyControl) {
            device.CloseDevice();
          }
          break;
        }
      }
      return false;
    }
    
    private void ChangeState(MD2AnimationType type) {
      if (controlNode != null && controlNodeState != type) {
        controlNodeState = type;
        controlNode.SetMD2Animation(controlNodeState);
      }
    }
    
  }
  
  class Init {
    [STAThread]
    public static void Main() {
      Viewer view = new Viewer(0, 0, 800, 600);
      Form form = new Form();
      form.SetBounds(0, 0, 800, 600);
      
      TextBox box = new TextBox();
      box.SetBounds(40, 550, 600, 20);
      //box.BackColor = System.Drawing.Color.Transparent; // これは無理
      box.BackColor = System.Drawing.Color.Violet;
      box.KeyDown += new KeyEventHandler(TextBoxEventHandler);
      
      form.Controls.AddRange(new Control[]{box, view.Control});
      form.Show();
      
      
      view.FileSystem.AddZipFileArchive("map-20kdm2.pk3");
      
      view.LoadMap("20kdm2.bsp", new Vector3D(-1370, -130, -1400));
      IAnimatedMeshSceneNode node = view.LoadObject("sydney.md2", "sydney.bmp");
      view.ControlNode = node;
      view.AttachCamera(node);
      IAnimatedMeshSceneNode node2 = view.LoadObject("faerie.md2", "faerie2.bmp");
      node2.Position = new Vector3D(50, 30, 0);
      
      //view.Gui.AddMessageBox("caption", "content", true, MessageBoxFlag.OK, null, -1);
      //IGUIElement w = view.Gui.AddWindow(new Rect(20, 20, 200, 100), true, "title", null, -1);
      //view.Gui.AddEditBox("content", new Rect(10, 30, 100, 30),true, w, -1);
      
      view.Run();
    }
    
    static void TextBoxEventHandler(object sender, KeyEventArgs args) {
      if (args.KeyCode == Keys.Enter) {
        TextBox box = sender as TextBox;
        box.Text = "";
      }
    }
  }
}

ほかにもGUIがいくつか使えるようにはなっているが、TrueType表示などはまだはいってないので、日本語はトーフ化します。日本語入力はもちろん無理。

日本語を書くにはSystem.Drawingでビットマップに書いてそれをテクスチャとして貼り付ければいいけど、いまのところテクスチャもファイルからしかのインタフェースがない(Irrlicht.NETの場合)のでこれも微妙。