/// <summary> /// 再生開始 /// </summary> public YanesdkResult Play() { lock (lockObject) { #if RELEASE_ON_STOP if (IsPlaying) { if (!paused) { InnerStop(); } paused = false; SMPEG.SMPEG_rewind(mpeg); // 巻き戻す } else { if (!Loaded && fileName != null) { YanesdkResult result = Load(fileName); if (result != YanesdkResult.NoError) { return(result); } } } #else Stop(); #endif readyToDraw = false; // 描画しなおされるまでは描画準備状態とする InnerPlay(); return(YanesdkResult.NoError); } }
/// <summary>指定されたファイル名の画像を読み込む。</summary> /// <remarks> /// /// ここで読み込んだリソースは、VideoCache(→UnmanagedResourceManager)が /// いっぱいになると自動的に解放する。 /// /// Bindするときにそのチェックを行ない、解放されていれば自動的に再構築するので /// 通常、意識する必要は無いが、解放~再構築されることがあるので /// ここで読み込んだテクスチャのピクセルを直接いじってはいけない。 /// /// 直接いじりたいなら、まずSurfaceに読み込ませて、それをSetSurfaceで設定してから /// 使うこと。あるいは、解放されないようにVideoCacheのLimitを調整するか、 /// 毎フレーム使用するなどして、解放されないようにすること。 /// </remarks> public YanesdkResult Load(string filename) { Release(); using (Surface tmpSurface = new Surface()) { YanesdkResult result = tmpSurface.Load(filename); if (result == YanesdkResult.NoError) { result = InnerSetSurface(tmpSurface, false); // surface,dup/init } if (result == YanesdkResult.NoError) { this.fileName = filename; // もし、ローダー以外からファイルを単に読み込んだだけならば、Reconstructableにしておく。 if (constructInfo == null) { constructInfo = new TextrueConstructAdaptor(filename, this.ColorKey); } // リソースサイズが変更になったことをcache systemに通知する // Releaseのときに0なのは通知しているので通知するのは正常終了時のみでok. CacheSystem.OnResourceChanged(this); } return(result); } }
// 大文字小文字違いだけのものはCLSに準拠しない(´ω`) /// <summary> /// 定義ファイルを読み込む /// /// 定義ファイルに書いてあるファイル名が実行ファイルからの相対pathなのか、それとも /// 定義ファイルの存在するフォルダからの相対pathなのかどうかは、 /// IsDefRelativePathオプションに従う。 /// </summary> public YanesdkResult LoadDefFile(string filename) { Release(); basePath = FileSys.GetDirName(filename); YanesdkResult result = reader.LoadDefFile(filename, OptNum); if (result == YanesdkResult.NoError) { Dictionary <int, FilenamelistReader.Info> .KeyCollection keys = reader.Data.Keys; foreach (int key in keys) { // ファイル名は定義ファイル相対pathならそのようにする if (IsDefRelativePath) { reader.Data[key].name = FileSys.MakeFullName(basePath, reader.Data[key].name); } ICachedObject obj = OnDefFileLoaded(reader.Data[key]); dict.Add(key, obj); } } return(result); }
public void Reconstruct() { if (IsLost) { // 派生クラス側で再実装してくれい。 YanesdkResult result = OnReconstruct(constructInfo); isLoadFailed = result != YanesdkResult.NoError; } }
/// <summary> /// RGB888 or RGBA8888のサーフェースを作成する。 /// </summary> /// <param name="x">サーフェースサイズ(x)</param> /// <param name="y">サーフェースサイズ(y)</param> /// <param name="bAlpha"> /// bAlphaがtrueのときはRGBA8888(1pixelがR,G,B,A各8bitα付き32bit) /// bAlphaがfalseのときはRGB888(1pixelがRGB各8bit,24bit) /// のサーフェースを作成する。 /// </param> /// <returns>失敗時には非0が返る。</returns> public YanesdkResult CreateDIB(int x, int y, bool bAlpha) { Release(); YanesdkResult result = CreateDIBstatic(out surface, x, y, bAlpha); // 作成が成功したときにのみ更新 // if ( result == YanesdkResult.NoError ) // this.alpha = bAlpha; return(result); }
private Yanesdk.Sound.Sound LoadSoundByPath(string path) { Yanesdk.Sound.Sound sound = new Yanesdk.Sound.Sound(); YanesdkResult result = sound.Load(path); if (result == YanesdkResult.NoError) { sound.Volume = 0.75f; return(sound); } else { throw new Exception("効果音「" + path + "」が読み込めません><"); } }
private Yanesdk.Sound.Sound LoadMusicByPath(string path) { Yanesdk.Sound.Sound musics = new Yanesdk.Sound.Sound(); YanesdkResult result = musics.Load(path, -1); if (result == YanesdkResult.NoError) { musics.Loop = -1; return(musics); } else { throw new Exception("BGM「" + path + "」が読み込めません><"); } }
private GlTexture LoadTextureByPath(string path) { GlTexture texture = new GlTexture(); texture.LocalOption.Smooth = false; YanesdkResult result = texture.Load(path); if (result == YanesdkResult.NoError) { return(texture); } else { throw new Exception("画像「" + path + "」を読み込めません><"); } }
/// <summary>フォントをオープンする。</summary> /// <remarks> /// <para> /// 指定するのは、フォント名。 /// indexは、ttc(true type collection=ttfが複数入ったフォントファイル)の /// ときに、何番目のものかを指定する。0番から始まる番号。 /// </para> /// <para> /// Windowsならフォルダは決まっているので、カレントとパスの通っている /// ところに無ければ、そこから取得する。 /// </para> /// <para> /// Linuxのほうは、カレント、あとパスの通っているところから取得する。 /// </para> /// </remarks> /// <example> /// 例) /// Windowsでは、 /// <list type=""> /// msgothic.ttc : MSゴシック /// msmincho.ttc : MS明朝 /// </list> /// <para> /// Linuxの場合、日本語フォントを用いる場合は、 /// GT書体 (東京大学多国語処理研究会) /// http://www.l.u-tokyo.ac.jp/GT/ /// などから持ってきて、msgothic.ttcやmsmincho.ttcとリネームして /// カレントフォルダに配置しておくようにしてください。</para> /// /// <para> /// フォントフォルダの検索に用いているAPIは、 /// win95の場合はIE4.0以降をインストールしてないとダメ /// win98以降は使える。 /// </para> /// </example> public YanesdkResult Load(string fontname, int fontsize, int index) { Release(); YanesdkResult hr = Load(FileSys.ReadRW(fontname), fontsize, index); if (hr != YanesdkResult.NoError) { // カレントにないので、SHGetSpecialFolderPath関数を使って // フォントディレクトリを取得して頑張ってみる。 string fontpath; switch (System.Platform.PlatformID) { case Yanesdk.System.PlatformID.Windows: fontpath = FileSys.ConcatPath(Environment.SystemDirectory, @"..\fonts"); break; case Yanesdk.System.PlatformID.Linux: fontpath = "/usr/share/fonts/ja/TrueType/"; break; case Yanesdk.System.PlatformID.MacOS: fontpath = "/System/Library/Fonts/"; break; default: throw null; } hr = Load(FileSys.ReadRW(FileSys.MakeFullName(fontpath, fontname)), fontsize, index); } if (hr == YanesdkResult.NoError) { fileName = fontname; // もし、ローダー以外からファイルを単に読み込んだだけならば、Reconstructableにしておく。 if (constructInfo == null) { constructInfo = new FontConstructAdaptor(fontname, fontsize, index); } } return(hr); }
/// <summary> /// .NET FrameworkのBitmapをベースにTexture化する。 /// </summary> /// <remarks>これがあれば、.NETのGraphics等で描画したものを /// テクスチャー化して描画できる。ただし、内部的には何度もメモリ /// コピーを行なう必要があるためあまり速くはない。なるべくなら動的には /// 行なわないほうが良い。</remarks> /// <code> /// Bitmap bmp = new Bitmap(100, 100); /// Graphics g = Graphics.FromImage(bmp); /// g.DrawLine(new Pen(Color.Aqua, 10), 0, 0, 100, 100); /// GlTexture txt = new GlTexture(); /// txt.SetBitmap(bmp); /// g.Dispose(); /// scr.Blt(txt, 100, 100); /// txt.Dispose(); /// </code> /// <param name="bmp"></param> /// <returns></returns> public YanesdkResult SetBitmap(global::System.Drawing.Bitmap bmp) { // 転送元と転送先のサイズが同じで転送先がα付きのときは // glTextureSubImageで転送したほうが良いのだが // そんなに再々呼び出すことはないので、このままにしておこう…。 Surface surface; YanesdkResult result = BitmapHelper.BitmapToSurface(bmp, out surface); if (result != YanesdkResult.NoError) { return(result); } this.SetSurface(surface); surface.Dispose(); return(YanesdkResult.NoError); }
private Sound LoadMusicByPath(string path) { Sound sound = new Sound(); YanesdkResult result = sound.Load(path, -1); if (result == YanesdkResult.NoError) { if (path.IndexOf("title") != -1 || path.IndexOf("clear") != -1 || path.IndexOf("ending") != -1) { sound.Loop = 0; } else { sound.Loop = -1; } return(sound); } else { throw new Exception("BGM「" + path + "」をロードできません><"); } }
private Sound LoadSoundByPath(string path) { Sound sound = new Sound(); YanesdkResult result = sound.Load(path); if (result == YanesdkResult.NoError) { if (path.IndexOf("voice") != -1) { sound.Volume = 0.9f; } else { sound.Volume = 0.4f; } return(sound); } else { throw new Exception("効果音「" + path + "」をロードできません><"); } }
// IntPtr oldContext; // ↑ // Win32WindowのSelectのネストが出来るようにしようと考えたのだが、 // 前のコンテキストを保存しておいても、 // Select // Select // Update ←このあと、1つ目のSelectのViewに設定しなおす必要があるのだが、 // このための復帰処理が難しい // Update // ので、こういう実装は現実的ではないと判断する。 // 初期化用のhelper関数 private YanesdkResult InitByHdc_(IntPtr hDc) { this.hDC = hDc; screen_ = new Screen2DGl(); screen_.BeginDrawDelegate = delegate { hDC = GetDC(this.hWnd); // oldContext = opengl32.wglGetCurrentContext(); Opengl32.wglMakeCurrent(this.hDC, this.hRC); // テクスチャー描画が基本なのでテクスチャーを有効にしておかねば }; screen_.EndDrawDelegate = delegate { SwapBuffers(this.hDC); Opengl32.wglMakeCurrent(this.hDC, IntPtr.Zero); ReleaseDC(this.hWnd, this.hDC); }; // 描画を行なわないdelegateを渡す。 // なぜなら、テクスチャの読み込みは、 // wglMakeCurrentが実行されていないと // 正しく読み込まれないので、beginDrawDelegateを行なってから // 読み込み、それが終わり次第この // delegateを呼び出して、openglのassignを解放してやる必要がある。 screen_.QuitDrawDelegate = delegate { Opengl32.wglMakeCurrent(this.hDC, IntPtr.Zero); // opengl32.wglMakeCurrent(this.hDC , oldContext); ReleaseDC(this.hWnd, this.hDC); }; YanesdkResult result = CreatePixelFormat(this.hDC); if (result != YanesdkResult.NoError) { return(result); } // Create a new OpenGL rendering contex this.hRC = Opengl32.wglCreateContext(this.hDC); // context共有を利用する。 // 0番は常に生きていると仮定。 // opengl32.wglShareLists(Singleton<GlInitializer>.Instance.hNullRC,this.hRC); // ↑これをやるとthreadが終了しなくなるので // 一つ目のRendering Contextだけ解放しないことにする。 if (theFirstHRc != IntPtr.Zero) { Opengl32.wglShareLists(theFirstHRc, this.hRC); } else { theFirstHRc = this.hRC; } ReleaseDC(this.hWnd, this.hDC); RECT32 rect = new RECT32(); // GetWindowRect((IntPtr)this.hWnd, out rect); GetClientRect((IntPtr)this.hWnd, out rect); Screen.UpdateView(rect.left - rect.right, rect.bottom - rect.top); return(YanesdkResult.NoError); }
/// <summary> /// mpegファイルを読み込む /// </summary> /// <param name="filename">ファイル名</param> public YanesdkResult Load(string filename) { lock (lockObject) { Release(); tmpFile = FileSys.GetTmpFile(filename); if (tmpFile == null || tmpFile.FileName == null) { return(YanesdkResult.FileNotFound); } // 読み込み。 //mpeg = SMPEG.SMPEG_new(tmpFile.FileName, ref info, SDL.SDL_WasInit(SDL.SDL_INIT_AUDIO) == 0 ? 1 : 0); mpeg = SMPEG.SMPEG_new(tmpFile.FileName, ref info, 0); if (SMPEG.SMPEG_error(mpeg) != null) { Debug.Fail(SMPEG.SMPEG_error(mpeg)); return(YanesdkResult.SdlError); // …SDL? } // 初期設定 // loop = false; // ループ設定はここでは変更しないほうが良い。 paused = false; SMPEG.SMPEG_enablevideo(mpeg, 1); SMPEG.SMPEG_enableaudio(mpeg, 0); if (info.has_audio != 0) { SDL.SDL_AudioSpec audiofmt = new SDL.SDL_AudioSpec(); audiofmt.format = (ushort)Sound.Sound.SoundConfig.AudioFormat; audiofmt.freq = (ushort)Sound.Sound.SoundConfig.AudioRate; audiofmt.channels = (byte)Sound.Sound.SoundConfig.AudioChannels; audiofmt.samples = (ushort)Sound.Sound.SoundConfig.AudioBuffers; SMPEG.SMPEG_actualSpec(mpeg, ref audiofmt); SDL.Mix_HookMusic(mix_hook, mpeg); SMPEG.SMPEG_enableaudio(mpeg, 1); } SMPEG.SMPEG_enableaudio(mpeg, 1); Volume = volume; // 描画先サーフェスのsmpegへの登録など。 if (window != null) { // SDLWindowに直に描画する if (surface != null) { surface.Dispose(); surface = null; } uint flags = (uint)window.Option; flags &= ~SDL.SDL_OPENGL; // OPENGLはダメ。 IntPtr s = SDL.SDL_SetVideoMode(window.Width, window.Height, window.Bpp, flags); if (s == IntPtr.Zero) { return(YanesdkResult.SdlError); } SMPEG.SMPEG_setdisplay(mpeg, s, IntPtr.Zero, null); SMPEG.SMPEG_move(mpeg, (int)windowRect.Left, (int)windowRect.Top); SMPEG.SMPEG_scaleXY(mpeg, (int)windowRect.Width, (int)windowRect.Height); } else if ( Yanesdk.System.Platform.PlatformID == Yanesdk.System.PlatformID.Windows && hwnd != IntPtr.Zero) { // SDLWindowを貼り付けてそれに描画する if (surface != null) { surface.Dispose(); surface = null; } // 親ウィンドウの位置・サイズを取得 POINT parentPos = new POINT(); ClientToScreen(hwnd, ref parentPos); RECT parentRect = new RECT(); GetClientRect(hwnd, out parentRect); int w = parentRect.right - parentRect.left, h = parentRect.bottom - parentRect.top; // SDLウィンドウの位置を合わせる IntPtr sdlHwnd = GetSDLWindowHandle(); //SetParent(sdlHwnd, hwnd); // これするとどうもバグる… SetWindowPos(sdlHwnd, IntPtr.Zero, parentPos.x, parentPos.y, w, h, SWP_NOZORDER); // SDLウィンドウの作成 uint flags = SDL.SDL_HWSURFACE | SDL.SDL_NOFRAME; IntPtr s = SDL.SDL_SetVideoMode(w, h, 0, flags); if (s == IntPtr.Zero) { return(YanesdkResult.SdlError); } sdlWindowCreated = true; sdlHwnd = GetSDLWindowHandle(); // 変わらないと思うが、一応再取得 if (sdlHwnd == IntPtr.Zero) { return(YanesdkResult.SdlError); } SetParent(sdlHwnd, hwnd); SetWindowPos(sdlHwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE); SMPEG.SMPEG_setdisplay(mpeg, s, IntPtr.Zero, null); SMPEG.SMPEG_move(mpeg, 0, 0); SMPEG.SMPEG_scaleXY(mpeg, w, h); } else { // surfaceに描画する if (surface != null && (!surface.CheckRGB888() || surface.Width != Width || surface.Height != Height)) { surface.Dispose(); surface = null; } if (surface == null) { surface = new Surface(); // 拡大・縮小はSMPEG側にやらせると重いので、原寸大で。 YanesdkResult result = surface.CreateDIB(Width, Height, false); if (result != YanesdkResult.NoError) { return(result); } } SMPEG.SMPEG_setdisplay(mpeg, surface.SDL_Surface, mutex, callback); SMPEG.SMPEG_move(mpeg, 0, 0); SMPEG.SMPEG_scaleXY(mpeg, surface.Width, surface.Height); //SetFilter(SMPEG.SMPEGfilter_null()); } this.fileName = filename; // おしまい。 return(YanesdkResult.NoError); } }
/// <summary> /// YanesdkResultをそのままエラーメッセージとするタイプ。 /// </summary> /// <param name="msg"></param> public YanesdkException(YanesdkResult msg) : this(msg.ToString()) { }
/// <summary> /// 例外の発生したオブジェクトとYanesdkResultをそのままエラーメッセージとするタイプ。 /// </summary> /// <param name="o"></param> /// <param name="msg"></param> public YanesdkException(object o, YanesdkResult msg) : this(o, msg.ToString()) { }
/// <summary> /// 定義ファイルの読み込み /// </summary> /// <para> /// ・定義ファイル仕様 /// </para> /// <para> /// file名 , 読み込み番号(load,getで指定するときの番号) , option1, option2 /// の繰り返し。読み込み番号,option1,2は省略可能。 /// 省略した場合、int.MinValue扱いになる。 /// </para> /// <para> /// 以下はコメント /// /// 読み込み番号が指定された場合、そのあとは連番になる。 /// 例) /// <list type="bullet"> /// <item><description>a.wav,2</description></item> /// <item><description>b.wav ← このファイルの番号は3になる</description></item> /// <item><description>c.wav ← このファイルの番号は4になる</description></item> /// </list> /// /// ここで指定されているoptionが、どのような意味を持つかは、 /// このCacheLoaderクラスを使用するクラス(派生クラス?)に依存する。 /// </para> /// <para> /// その他、細かい解析ルールは、 CSVReader クラスの内容に依存する。 /// </para> /// /// optNum : optionの書いてある限度位置(列)を指定する。 /// 上の例では、「a.wav , 2」なので、optNum = 0(なし)と考えることが出来る。 /// 「a,wav , opt1, opt2 , 2」のようにopt1,opt2を指定するならば、 /// optNum = 2と考えることが出来る。 /// 「a,wav , opt1, 2 , opt2」のようにopt1,opt2を指定するならば、 /// optNum = 1と考えることが出来る。 /// /// </remarks> /// <param name="filename"></param> public YanesdkResult LoadDefFile(string filename, int optNum) { Release(); YanesdkResult result = reader.Read(filename); if (result != YanesdkResult.NoError) { return(result); } // 読み込んだCSVから、ファイル名と番号とを対応させ、 // LinkedListに格納していく。 int line = 0; List <List <string> > list = reader.CsvData; foreach (List <string> a in list) { int opt1 = int.MinValue, opt2 = int.MinValue; for (int i = 0, j = 0; i < 3; ++i) { int opt = int.MinValue; if (a.Count < i + 2) { break; } int n; if (int.TryParse(a[i + 1], out n)) { // 成功した if (i == optNum) { line = n; continue; } else { opt = n; } } // opt[j] = n; switch (j) { case 0: opt1 = opt; break; case 1: opt2 = opt; break; } ++j; } try { dic.Add(line, new Info(a[0], opt1, opt2)); } catch { // おそらくは、同一の値で定義されている行によるエラーなのだが.. // この行スキップしたろか #if DEBUG global::System.Console.WriteLine("FilenamelistReader.loadDefFileでエラー行検出。"); #endif } ++line; } return(YanesdkResult.NoError); }