-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
プログラム実行時、モデルの動きにCollisionPolygon2Dを追従させたい #41
Comments
@creeper-0910 もしそうでしたら、 CollisionPolygon2D を用意しなくても指定した座標とLive2D内のHitAreaやTriangleとのコリジョンを取る事が出来ますよ。 こちらはまだ API として公開する形を決めかねているのですけど、実装自体は完了していまして、 0.3系のデモに demo_effect_hit_area.tscn というサンプルを追加しています。 こちらは以下の要望を満たすために用意しました。
画面としては以下の様なものなのですが、動かしてみてもらえると理解しやすいと思います。お手元の 0.3 をアップデートして再ビルドを行うと利用可能になります。 そうではなく、単純に塗りつぶしたポリゴンが欲しいという場合でしたら、 GDCubismUserMode の get_meshes から計算で得る方法もあります。 get_meshes で得られるデータは実際に描画に使用した頂点情報が格納されていますので、パーツ単位でよければ完全に一致した情報が得られます。
もうすこし具体的な目的が教えていただければ、より適した方法が提案出来るかもしれません。 |
返信ありがとうございます、 |
デスクトップマスコット風にしたいのでしたら、 Godot Engine の本体機能を使って実現できますよ。
GDCubism では demo/addons/gd_cubism/example/demo_transparent.tscn というサンプルを用意していますので、そちらを実行してみてください。 具体的には以下の様なスクリプトを使って実現できます。 var enable_transparent: bool = true
get_tree().root.transparent_bg = enable_transparent
# 描画していない場所を透過
DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_TRANSPARENT, enable_transparent, 0)
# 常に最前面に表示
DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_ALWAYS_ON_TOP, true, 0) Window が透明になっても見た目が透けているだけで Window 枠は依然として存在しています。
以下はXに貼り付けている動画(内容は上のスクリーンショットと同じもの)です。 |
こちらClickを除外したいという部分を失念していました。 画像データの透過処理は上で述べている方法で解決できますので、余計な部分にマウスを反応させたくない、というのをどうするかとなりますね。 処理としては
提示されている画像では Live2Dモデルを綺麗にくり抜いていますが、自動生成で行おうとするとやや手間となりますので、ここでは周囲を囲むポリゴンを作る問題に置き換えます。 以下の様なイメージです。 凸包について もしかしたら考える楽しさを奪ってしまうかもしれませんが、説明するのはちょっと難しいのでここではそういうものがあると捉えてください。 ここでは凸包を求めるのに Graham Scan という手法を用います。 GDScript で記述すると以下の様になります。 func check_cross(ary_check: Array, v: Vector2) -> bool:
var va: Vector2 = ary_check[ary_check.size() - 2]
var vb: Vector2 = ary_check[ary_check.size() - 1]
return (((vb.x - va.x) * (v.y - va.y)) - ((vb.y - va.y) * (v.x - va.x))) > 0
func convex_hull(ary_vertex: Array) -> Array:
ary_vertex.sort()
var ary_result: Array
var n = ary_vertex.size()
for vtx in ary_vertex:
while ary_result.size() > 1 and check_cross(ary_result, vtx):
ary_result.pop_back()
ary_result.push_back(vtx)
var t = ary_result.size()
var i = n - 2
while i >= 0:
var vtx: Vector2 = ary_vertex[i]
while ary_result.size() > t and check_cross(ary_result, vtx):
ary_result.pop_back()
ary_result.push_back(vtx)
i -= 1
ary_result.pop_back()
return ary_result この関数を func _process(delta):
var dict_mesh = $Sprite2D/GDCubismUserModel.get_meshes()
var ary: PackedVector2Array
# ArtMesh121 といった名称はLive2Dモデル毎に異なります。
ary += dict_mesh["ArtMesh121"].surface_get_arrays(0)[Mesh.ARRAY_VERTEX]
ary += dict_mesh["ArtMesh122"].surface_get_arrays(0)[Mesh.ARRAY_VERTEX]
ary += dict_mesh["ArtMesh135"].surface_get_arrays(0)[Mesh.ARRAY_VERTEX]
ary += dict_mesh["ArtMesh146"].surface_get_arrays(0)[Mesh.ARRAY_VERTEX]
ary += dict_mesh["ArtMesh147"].surface_get_arrays(0)[Mesh.ARRAY_VERTEX]
ary += dict_mesh["ArtMesh231"].surface_get_arrays(0)[Mesh.ARRAY_VERTEX]
ary += dict_mesh["ArtMesh278"].surface_get_arrays(0)[Mesh.ARRAY_VERTEX]
var ary_poly = convex_hull(ary)
# ここでは Polygon2D がノードツリーに存在しているとしています。
# 直接 PackedVector2Array を渡せますが、 Polygon2D を経由すると表示が確認できるので。
$Polygon2D.polygon = PackedVector2Array(ary_poly)
DisplayServer.window_set_mouse_passthrough($Polygon2D.polygon) 結構重たい処理になりますので、基本姿勢の状態を一回だけ生成したり HitArea のみを生成するといった方法を併用するのが良さそうです。 参考になりましたらどうぞ。 |
@creeper-0910 demo / addons / gd_cubism / example に保存ざれている demo_transparent.tscn を動かして貰えると、手元で実際の挙動が確認出来るかと思います。 |
遅くなってしまい申し訳ございません。 |
こちらのIssue、だいぶ経過していますどうでしょうか。 |
報告ありがとうございます。 |
This is likely a windows limitation - Window - mouse_passthrough_polygon
There was another attempt at mouse passthrough using just transparent pixels of the viewport via Windows API calls which may have to be applied here: Other noteworthy issues: |
@Haledire @creeper-0910 I initially thought that the This was my misunderstanding. If we apply the previously mentioned convex hull to all ArtMeshes, we would obtain a rather large Polygon2D that covers all drawing areas. Alternatively, we could consider the following methods:
Does this look good to you? 情報ありがとうございます。 これは私が勘違いしていました。申し訳ありません。 前述した凸包を全てのArtMeshに対して行えば、全ての描画領域をカバーするかなり大きな Polygon2D を得られるとは思いますが、少なくとも毎フレーム行うにはかなり重い処理となります。 それ以外の方法でしたら、以下の様な方法でしょうか。
高速に描画領域を包む Polygon2D を生成するというのはなかなか難しそうです。 |
I have reviewed the Godot Engine source code and noticed a discrepancy between the names and functions. Upon examining each implementation, it appears that on macOS, the function filters mouse events within a specified range, as the name suggests.
While both filtering mouse events and clipping the drawing area achieve the same goal of “not accepting mouse events within a region,” the processes and purposes are entirely different, making the current naming inappropriate. Nevertheless, it seems that this is the intended behavior in Godot Engine.
|
@creeper-0910 現在の状況についてデスクトップマスコットを実装するアプローチとしては Window の透明化とマウスイベントのフィルタリング(クリックスルー)を用いるというのは妥当なアプローチのようです。 そして、マウスイベントのフィルタリング処理を行うために、 という状況となっています。 解決方法について@Haledire さんが解決方法の一つを提案されています。 他にも元々のアプローチである手動でPolygon2Dを用意する、描画領域を全て包む様なPolygon2Dを動的に生成する、というものが考えられるのですが、労力や処理負荷という面からはあまりお薦めできません。 問題の技術的背景について私の方で Godot Engine のソースを読んだところ、 Windows 版での Windows版の Godot Engine で より望ましい動作にするには、 /platform/windows/display_server_windows.cpp 内の処理を修正することとなります。 具体的には macOS 版の実装を参考に、 こちらは受け取って貰えないかもしれませんが、 Godot の Issue に投稿しようと思います。 具体的な解決が出来ずに申し訳ありません。 @creeper-0910 Current SituationUsing window transparency and mouse event filtering (click-through) seems to be a reasonable approach for implementing a desktop mascot. However, when using Proposed Solutions@Haledire has suggested one possible solution. Other approaches include manually preparing a Technical Background of the IssueUpon reviewing the Godot Engine source code, I noticed an issue with the implementation of The reason To achieve the desired behavior, the processing in Specifically, by referring to the macOS implementation, we can perform region checks using I am considering posting this on the Godot Issue tracker, although I am not sure if it will be accepted. I apologize for not being able to provide a concrete solution. |
返信遅くなってしまい申し訳ございません。 and Thank you so much @Haledire ! |
live2dモデルを使用する際に、モデルの形や動きに合わせたCollisionPolygon2Dを生成したいと考えているのですが、可能でしょうか?
お時間のあるときに確認していただけると幸いです。
(下記は手動で作成したものですが、実行時のモデルの動きに追従させることができなかったため使用できませんでした。)
The text was updated successfully, but these errors were encountered: