mieki256's diary



2020/01/20(月) [n年前の日記]

#1 [love2d] Love2Dのウインドウにドロップされたpng画像を表示

任意の場所に置いてある png画像を、エクスプローラ等のファイラーから Love2Dのウインドウにドラッグアンドドロップ(D&D)して表示することができそうか実験してみたり。環境は、Windows10 x64 1909 + Love2D 11.3。

実験の動機。 :

Love2D を使って何かしらのツールを作成するとして、どうやって画像ファイルその他を渡してやればいいのか、ちょっと悩んでしまった。もしかすると、Love2D は、ファイル選択ダイアログの類は持っていない・利用できないのではないか…。

まあ、エクスプローラから画像ファイルを、そのウインドウにD&Dしてやれば、ひとまずどうにかなるんじゃないか。でも、そんなこと、Love2D はできるのだろうか。ということで、ちょっと実験。

結果。 :

一応出来た。と思う。たぶん。



png画像をD&Dして、表示される画像を変更できた。

ただ、今回のソースは png画像にしか対応させてないので、gif画像を渡すとエラーを出して停止する…。仕様です。

ソース。 :

_conf.lua
function love.conf(t)
  t.version = "11.3" -- love2d version
  t.window.title = "File Dropped - love2d"
  t.window.vsync = 1
  t.window.width = 640
  t.window.height = 480
  t.window.msaa = 8

  -- t.window.fullscreen = true
  -- t.window.fullscreentype = "exclusive"
end

_main.lua
function love.load()
  font = love.graphics.newFont(12)

  filepath = ""
  loadreq = false

  img = nil
  scalev = 0
  angle = 0
end

function love.update(dt)
  if loadreq then
    -- load png image
    loadreq = false
    local f = io.open(filepath, "rb")
    local contents = f:read("*all")
    local data = love.filesystem.newFileData(contents, "temp.png")
    local imgdata = love.image.newImageData(data)
    f:close()
    img = love.graphics.newImage(imgdata)
  end

  scalev = 0.1 * math.sin(math.rad(angle))
  angle = (angle + 540 * dt) % 360.0
end

function love.draw()
  -- clear canvas
  love.graphics.clear(0.2, 0.2, 0.2, 1.0)

  -- draw image
  love.graphics.setColor(1.0, 1.0, 1.0, 1.0)
  if img ~= nil then
    local scrw, scrh = love.graphics.getDimensions()
    local w = img:getWidth()
    local h = img:getHeight()
    local x = scrw / 2
    local y = scrh - 16
    local ox = w / 2
    local oy = h
    local yscale = 1.0 + scalev
    local xscale = (w * h) / (h * yscale) / w
    love.graphics.draw(img, x, y, 0, xscale, yscale, ox, oy)
  end

  -- draw text
  love.graphics.setFont(font)
  love.graphics.setColor(1, 1, 1, 1)
  love.graphics.print("Please drop the png image file", 220, 2)
  love.graphics.print(filepath, 2, 40)
  love.graphics.print("FPS: " .. tostring(love.timer.getFPS()), 2, 2)
end

function love.keypressed(key, isrepeat)
  if key == "escape" then
    -- ESC key to exit
    love.event.quit()
  end
end

function love.filedropped(file)
  filepath = file:getFilename()
  loadreq = true
end

少し解説。 :

Love2D のウインドウに、何かがドラッグアンドドロップされた時は、love.filedropped() というメソッドを(もし用意してあるのなら)呼んでくれるらしい。渡された変数から、ファイルのパス(C:\hoge\fuga\piyo.png みたいな文字列)も得られるので、どの場所の、何のファイルがドロップされたのかを知ることができる。

であれば、渡されたそのファイルを開いてしまえばあっさりOK ―― というわけにはいかないようで。

Love2D は、ファイルアクセスに関して、セキュリティ面を意識して制限が設けられているのだとか。なんでも、以下の2種類のフォルダにしかアクセスできないそうで。
  • main.lua等のソースファイルが置かれているフォルダ。
  • ゲームのセーブデータを保存できる特定のフォルダ。

例えば、「画像ファイルを読み込んでウインドウ内に表示したい」場合は…。その画像ファイルは、えてして、ソースフォルダ以下(ソースフォルダ内に作ったサブフォルダも含む)に置いておかないといけない。他の場所に置いてあると、「そんなファイルは存在しねえよ!(だって俺そんな場所にアクセスできないもん、あるかどうかを調べることすらできないもん)」とエラーを出してしまう。

しかし、そんな仕様では、ツールの類を作りたい時に困ってしまうわけで…。ユーザは、自分の把握しやすい場所に、作業用のファイルを置いておきたいはずなので…。「この場所に絶対置け!」と強制されちゃうツールなんて、不便極まりないわけで…。

そこで、一応抜け道モドキが用意されているらしい。Love2D が持っているファイル関係APIではなく、Lua が持ってる標準的なファイル関係APIを使えば、任意の場所からファイルを読み込めるそうで。

コミュニティの掲示板を眺めた感じでは、「セキュリティ上推奨できないけれど、どうしてもそういうことをしたかったら、こういうやり方でどうにかするしかないだろうねえ」みたいな雰囲気を感じたり。

具体的な手順としては…。一例として、png画像を読み込んで画像描画に使う Image に変換したい場合、以下のような流れになる模様。
  1. Lua の io.open() を使って、ファイルを開く。
  2. Lua の File.read() を使って、ファイルの中身を全部読み込む。
  3. Love2D が持っている仮想ファイルシステム上で、ファイルの中身を使って、仮ファイル(?)を生成する。
  4. 仮ファイルから、ImageData を作る。
  5. ImageData から、Image を作る。

上記のソースでは、love.update(dt) の中で、この手順を使ってpng画像を読み込んでいる。
    local f = io.open(filepath, "rb")
    local contents = f:read("*all")
    local data = love.filesystem.newFileData(contents, "temp.png")
    local imgdata = love.image.newImageData(data)
    f:close()
    img = love.graphics.newImage(imgdata)

ただ、この場合、ドロップされるファイルは png画像のはず、と決め打ちして書いてある。例えば gif画像をドロップすると、「コレ、png画像のフォーマットじゃないから開けないよ」とエラーを出して止まってしまう。

本来なら、せめてファイルの拡張子をチェックして、Love2D が扱えるファイル種類かどうか判定して、扱えるファイル種類なら対応した仮画像ファイル名を渡して処理をすべき、なのだろうなと…。今回はそこまでやってないけど。

参考ページ。 :


以上です。

過去ログ表示

Prev - 2020/01 - Next
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project