D언어+SDL2로 비사각형 창 만들기
개요
SDL_CreateShapedWindow
및 SDL_SetWindowShape
로 비사각형 창 만들기경위
SDL2에서는 비사각형(캐릭터나 도형의 형태)의 윈도우를 작성할 수 있다고 들었으므로, 조사해 보았습니다.
처음 「SDL 비구형」으로 구그 했습니다만, 「SDL2.0의 새로운 기능」의 곳에서 소개되고 있는 정도로,
정보를 찾을 수 없습니다. (어째서··)
어쩔 수 없이 일본어 자료를 포기하고, 영어 기사나 Mercurial에 있는 소스 코드SDL_CreateShapedWindow
와 SDL_SetWindowShape
라는 함수가 그렇다는 것을 알았습니다.
htps : // 우우키.ぃbsdl. 오 RG / SDL
htps: //hg.ぃbsdl. rg/SDL/후에/704아0b후 cf75/src/ゔぃ로/SDL_샤페. c
htps: //hg.ぃbsdl. rg/SDL/훗/704아0b후 cf75/에서 st/에서 st샤페. c
그건 그렇고, SDL은 C 언어 라이브러리이지만 DerelictSDL2라는 바인딩으로 D 언어에서 그대로 사용할 수 있습니다.
샘플
프로젝트 배치
프로젝트 배치
런타임
SDL 공식 로부터 아카이브를 취득·전개 후, 상기와 같이 배치한다
소스 코드
이쪽을 참고로 했습니다.
「프로그램으로 고사리 그리기」를 D언어+SDL2+dub로 그리기
고마워요.
souce/app.d
import std.exception;
import std.string;
import std.c.string;
import derelict.sdl2.sdl;
/// SDLのロード
static this()
{
DerelictSDL2.load("./library/SDL2.dll");
}
/// メイン関数
void main()
{
// SDL初期化
enforceSdl(SDL_Init(SDL_INIT_EVERYTHING) == 0);
scope(exit) SDL_Quit();
// ウィンドウの生成
auto window = enforceSdl(SDL_CreateShapedWindow(
toStringz("SDL_CreateShapedWindow test"),
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
640, 480,
SDL_WINDOW_BORDERLESS));
scope(exit) SDL_DestroyWindow(window);
// レンダラーの生成
auto renderer = enforceSdl(SDL_CreateRenderer(window, -1, 0));
scope(exit) SDL_DestroyRenderer(renderer);
// 背景画像の読み込み
auto surface = enforceSdl(SDL_LoadBMP(toStringz("./image/background.bmp"))); //<- 背景が緑色の画像
scope(exit) SDL_FreeSurface(surface);
// 透過色の指定
SDL_WindowShapeMode mode;
mode.mode = ShapeModeColorKey;
mode.parameters.colorKey = SDL_Color(0, Uint8.max, 0, Uint8.max);
auto texture = enforceSdl(SDL_CreateTextureFromSurface(renderer, surface));
scope(exit) SDL_DestroyTexture(texture);
// 非矩形ウィンドウに設定
SDL_Rect srcRect;
enforceSdl(SDL_QueryTexture(texture, null, null, &srcRect.w, &srcRect.h) == 0);
SDL_SetWindowSize(window, srcRect.w, srcRect.h);
SDL_SetWindowShape(window, surface, &mode);
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
// 描画実行
enforceSdl(SDL_RenderCopy(renderer, texture, null, null) == 0);
SDL_RenderPresent(renderer);
// イベントループ
mainLoop: for (SDL_Event event; SDL_WaitEvent(&event);)
{
switch (event.type)
{
// ウィンドウクローズで終了
case SDL_QUIT:
break mainLoop;
// ESCキー押し下げで終了
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE)
break mainLoop;
break;
default:
break;
}
}
}
/**
* SDLのエラーメッセージの取得
*
* Returns:
* SDLのエラーメッセージ。エラーが無ければnull。
*/
string getSdlMessage() @trusted
{
if (auto msg = SDL_GetError())
{
SDL_ClearError();
return msg[0 .. strlen(msg)].idup;
}
else
{
return null;
}
}
/**
* SDL関数のエラーチェック
*
* Params:
* value = SDL関数の戻り値か、エラーチェック結果。
* Returns:
* エラーが発生していなければvalue。
* Throws:
* Exception エラーが発生していた場合にスローされる。
*/
T enforceSdl(T)(T value, string file = __FILE__, size_t line = __LINE__)
{
return enforce(value, getSdlMessage(), file, line);
}
dub.json
{
"name": "shapedwindow",
"targetType": "executable",
"description": "A non-rectunglar window test written by D language.",
"dependencies": {
"derelict-sdl2": "1.2.8"
}
}
빌드
콘솔
dub
결과
[before]
[after]
비사각형 창을 만들 수 있었습니다만, 배경(녹색)의 일부가 투과되지 않고 보이고 버립니다.
texture에서 renderer로 복사할 때 확대 축소가 일어나고 있는(?)일지도 모릅니다만, 모릅니다.
또한 현재 (2015.8.25) SDL 공식으로 배포되고있는 SDL2.0.3에서는
SDL_SetWindowHitTest
가 구현되지 않았기 때문에,제목 표시줄이 없는 비사각형 창은 마우스 드래그로 이동할 수 없습니다.
(마우스 이벤트와
SetWindowPosition
로 자전으로 노력하면 할 수 있을지도 모릅니다만)다음 SDL2.0.4에서
SDL_SetWindowHitTest
가 구현되는 를 기다리는 것이 무난한 생각이 들었습니다.(DerelictSDL2의 해당 의미에서)
우선 당초 알고 싶었던 것은 확인할 수 있었으므로, 좋다고 합니다. . .
감상
Reference
이 문제에 관하여(D언어+SDL2로 비사각형 창 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/nak2yoshi/items/1411fbb65ccf82545e65텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)