====== 立体コメント落下(わんコメ対応) ======
**[[deliverytool/onecomme/plugin]]**でYouTube・ニコニコ生放送のコメントを受信して立体コメントを落下させるVCIのサンプルです。
* [[https://developer.virtualcast.jp/vci-docs/manual/osc/onecomme_osc/index.html|プラグインの仕様ドキュメント]]
* [[https://developer.virtualcast.jp/vci-docs/api/classes/ExportSolidComment/CreateSolidComment.html|立体コメントの仕様ドキュメント]]
\\
=== サンプルデータ ===
https://virtualcast.jp/products/db9e5adb6000be4f6a426925cf1a82cb85cc03c81977b5b86d7023d7c144d9a7
=== Unitypackage ===
{{ vci:sample:oscapi:onecomme:CommentDrop.unitypackage |}}
===== コンポーネント設定 =====
VCI Object
{{:vci:sample:oscapi:onecomme:CommentDrop1.png?direct}}
===== VCIスクリプト =====
--------------------------------------------------------------
---立体コメント落下VCI
---
---機能
---わんコメプラグインより、画像URLがOSCにて送信されると、コメントの内容を立体コメントとして落下する
---
---機能詳細
--- ●本VCIはわんコメプラグイン(Ver.1.2.0以上)と連携して動作するVCIである
--- ●自分自身のわんコメのOSCと、自身のVCIの組み合わせのみ動作する
--- ●OSCにてコメント情報を受信すると立体コメントを落下させる
--- ●落下させる立体コメントの寿命は15秒
--- ●立体コメントの色は、選択されたカラーパレットによって決まる
--- ●プレーン君を操作することで、立体コメントの落下位置を調整することができる
--- ●プレーン君の数値操作は、アイテムオーナーのみが可能
--- ●オーナー以外は、設定値(吹き出し)は非アクティブ
--- ●1秒以上のUSEで、落下基準点の切り替え(「プレイヤー中心」と「スイッチ中心」)
--- ●1秒未満のUSEで、落下位置操作切り替え(「範囲」と「オフセット」)
--- ●プレーン君の拡縮操作で、「範囲」または「オフセット」の数値操作
--- ●上記の位置は、ローカルストリームカメラ、または、モニタ、の方向を向くような基準となる
--- ●上記の向きの基準は、ローカルストリームカメラが出ている場合はそちらを基準に、出てない場合はモニタが基準となる
--- ●設定吹き出しのパレットマークをUseすると、カラーパレットの選択画面のON/OFFが操作できる
--- ●表示された選択画面の、カラーパレットをUseすると、そのカラーパレットを選択できる
--------------------------------------------------------------
local displayModule = require("planeKunDisplay")
local solidComment = require("SolidComment")
local myId
local ownerId
local switchFlag = false
local switchUseFlag = false
local switchGrabFlag = false
local switchUseStartTime = 0
local switchIntervalTime = 1
local dropRange = {"2.00","0.00","0.50"}
local dropOffset = {"0.00","3.00","0.00"}
local preScl = Vector3.one
local switchFase = 1
local nxtState = {0,0,0}
local switchCollider = vci.assets.GetTransform("ButtonRootCollider")
local switch = vci.assets.GetTransform("ButtonRoot")
local queueMax = 15
local queueOutInterval = 0.3 --キューチェックのインターバル
local queueOutPreTime = 0 --前回のキューチェックの時間
local commentQueueTbl = {} --キューテーブル
local heightOffset = 0
---OSCアドレス
local commonAdress = "/vc-official/onecomme/common"
--- ---------------------------------------------------------
--- OSC受信時の処理
--- ---------------------------------------------------------
--- OSC受信データをバッファ用テーブルに保存する。
--- メッセージの流量を制限するため、バッファを設けている。
--- 保存時、設定した保存限界を超えたデータは、古いものから削除する。
--- @param content table @OSCからの取得データ
local function commentDrop(content)
if ownerId ~= nil then
if ownerId == myId then
local oscData = json.parse(content)
--文字数制限処理
if #oscData.comment > 15 then
oscData.comment = oscData.comment:sub(1, 15)
end
table.insert(commentQueueTbl, oscData.comment)
--キューに貯まりすぎないよう、上限を超えたら古いコメントを削除
while #commentQueueTbl > queueMax do
table.remove(commentQueueTbl, 1)
print("キュー上限を超えたので、キュー内の古いコメントを削除しました")
end
end
end
end
vci.osc.RegisterMethod(commonAdress, commentDrop, {ExportOscType.BlobAsUtf8})
--- キューから、立体コメントを生成する処理
local function outputFromQueue()
if #commentQueueTbl ~= 0 and os.time() - queueOutPreTime > queueOutInterval then
local spawnPos = switch.GetPosition()
--スイッチがオーナー基準の場合、オーナーの位置を取得
if not(switchFlag) then
spawnPos = vci.vc.room.GetLocalPlayer().GetPosition()
end
--ランダム化の位置設定
local randomPos = Vector3.__new(
(math.random()-0.5)*2*dropRange[1] + dropOffset[1],
(math.random()-0.5)*2*dropRange[2] + dropOffset[2],
(math.random()-0.5)*2*dropRange[3] + dropOffset[3]
)
--基準向きの取得
local spawnRot = Quaternion.identity
--ローカルストリームカメラの有無のチェック
local camera = vci.vc.room.streamCamera.GetLocalStreamCameraByPlayerId(ownerId)
local monitor = vci.vc.room.monitorCamera
if camera.IsAvailable() then
local tempRot = camera.GetRotation().eulerAngles
tempRot.x = 0
tempRot.z = 0
spawnRot = Quaternion.Euler(tempRot)*Quaternion.Euler(0,180,0)
elseif monitor.GetRotation() ~= nil then
local tempRot = monitor.GetRotation().eulerAngles
tempRot.x = 0
tempRot.z = 0
spawnRot = Quaternion.Euler(tempRot)*Quaternion.Euler(0,180,0)
end
--コメント落下位置の、カメラの向き基準でのランダム化処理
spawnPos = spawnPos + spawnRot*randomPos
--コメントのスケールのランダム設定
local solidScl = 0.2*(math.random()-0.5) + 0.35
--コメントの生成処理
solidComment.commentDrop(spawnPos, spawnRot, solidScl, commentQueueTbl[1])
--生成したコメントの、キューからの削除
table.remove(commentQueueTbl, 1)
queueOutPreTime = os.time()
end
end
------------------------------------------------------------
---Initialize処理
------------------------------------------------------------
--- スタジオでは、オブジェクトを非アクティブに
local function initialize()
--ルームの識別
if vci.vc.GetSpaceType() == ExportVcSpaceType.Studio then
vci.assets.GetTransform("/ButtonRoot/FukidashiObj").SetActive(false)
vci.assets.GetTransform("Yajirushi").SetActive(false)
vci.assets.GetTransform("planekun").GetSkinnedMeshRenderer().SetBlendShapeWeight(7, 100)
--パレットオブジェクトの非アクティブ化
solidComment.inactive()
elseif vci.vc.GetSpaceType() == ExportVcSpaceType.Room then
myId = vci.vc.room.GetLocalPlayer().GetId()
--パレットオブジェクトの非アクティブ化
solidComment.inactive()
if vci.assets.IsMine then
if vci.state.Get("OwnerID") == nil then
--stateの初期化処理
vci.state.Set("OwnerID", myId)
vci.state.Set("Range", dropRange)
vci.state.Set("Offset", dropOffset)
vci.state.Set("Switch", false)
displayModule.textUpdate(switchFase, switchFlag, true)
ownerId = myId
--カラーパレット用のスイッチのアクティブ化
solidComment.paletteSwitchActive(true)
elseif vci.state.Get("OwnerID") == myId then
switchFlag = vci.state.Get("Switch")
dropRange = vci.state.Get("Range")
dropOffset = vci.state.Get("Offset")
displayModule.textUpdate(switchFase, switchFlag, true)
ownerId = myId
--カラーパレット用のスイッチのアクティブ化
solidComment.paletteSwitchActive(true)
--カラーパレットの番号の読み出し処理
solidComment.readState()
else
vci.assets.GetTransform("/ButtonRoot/FukidashiObj").SetActive(false)
vci.assets.GetTransform("Yajirushi").SetActive(false)
end
else
vci.assets.GetTransform("/ButtonRoot/FukidashiObj").SetActive(false)
vci.assets.GetTransform("Yajirushi").SetActive(false)
end
--プレーン君の表情切り替え
vci.assets.GetTransform("planekun").GetSkinnedMeshRenderer().SetBlendShapeWeight(0, 100)
end
end
initialize()
function updateAll()
--スイッチのコライダーの追従処理
if switchCollider.IsMine then
switch.SetPosition(switchCollider.GetPosition())
switch.SetRotation(switchCollider.GetRotation())
end
--スイッチ操作
if ownerId == myId then
outputFromQueue()
if switchGrabFlag then
nxtState = displayModule.textUpdateGrabbing(switchFase, preScl)
end
end
solidComment.updateAll()
end
function onGrab(item)
if ownerId ~= nil then
--プレーン君の操作
if item == "ButtonRootCollider" and ownerId == myId then
switchGrabFlag = true
--数値操作用のスケールの用意
preScl = {
switchCollider.GetLocalScale().x,
switchCollider.GetLocalScale().y,
switchCollider.GetLocalScale().z
}
end
end
end
function onUngrab(item)
if ownerId ~= nil then
--プレーン君の操作
if item == "ButtonRootCollider" and ownerId == myId then
switchGrabFlag = false
--数値操作用のコライダーリセット
switchCollider.SetLocalScale(Vector3.one)
--範囲・オフセットの上書き処理
if switchFase == 1 then
dropRange = nxtState
vci.state.Set("Range", dropRange)
vci.message.EmitToSelf("ThumbnailDropRangeSend", dropRange)
else
dropOffset = nxtState
vci.state.Set("Offset", dropOffset)
vci.message.EmitToSelf("ThumbnailDropOffsetSend", dropOffset)
end
end
end
end
function onUse(use)
if ownerId ~= nil then
--プレーン君の操作
--長押し・短押しの判定用のカウント開始
if use == "ButtonRootCollider" and ownerId == myId then
if not(switchUseFlag) then
switchUseFlag = true
switchUseStartTime = os.time()
end
end
solidComment.onUse(use)
end
end
function onUnuse(use)
if ownerId ~= nil then
--プレーン君の操作
--1秒以上「USE」長押し:基準の切り替え
--1秒未満「USE」:範囲とオフセットの切り替え
if use == "ButtonRootCollider" and ownerId == myId then
if switchUseFlag and os.time() - switchUseStartTime >= switchIntervalTime then
switchFlag = not(switchFlag)
if switchFlag then
heightOffset = switch.GetPosition().y - vci.vc.room.GetLocalPlayer().GetPosition().y
if heightOffset < 0 then
heightOffset = 0
end
end
dropOffset[2] = displayModule.baseSwitchHeightAdjust(switchFlag, switchFase, heightOffset)
vci.state.Set("Offset", dropOffset)
vci.state.Set("Switch", switchFlag)
vci.message.EmitToSelf("ThumbnailSwitchChange", {switchFlag, dropOffset})
displayModule.textUpdate(switchFase, switchFlag, false)
else
if switchFase == 1 then
switchFase = 2
else
switchFase = 1
end
displayModule.textUpdate(switchFase, switchFlag, false)
end
switchUseFlag = false
end
end
end
function onTriggerEnter(item, collider)
if ownerId ~= nil then
solidComment.onTriggerEnter(item, collider)
end
end
function onTriggerExit(item, collider)
if ownerId ~= nil then
solidComment.onTriggerExit(item, collider)
end
end
local displayModule = {}
local switchCollider = vci.assets.GetTransform("ButtonRootCollider")
local max = {{5,2,5},{5,7,5}}
local min = {{0,0,0},{-5,0,-5}}
---四捨五入
---@param x number @対象の数字
---@param digit number @有効数字(ex. 10, 1, 0.1...)
---@return number @四捨五入された後の数字
local function shishagonyu(x, digit)
return (math.floor(x/digit + 0.5))*digit
end
---スイッチのテキストアップデート
---@param switchFase boolean @表示は「出現範囲」か「出現オフセット」か
---@param switchFlag boolean @基準位置がスイッチかどうか。
---@param initialFlag boolean @初期化処理かどうか。オーナー名を入れるかどうかの処理
function displayModule.textUpdate(switchFase, switchFlag, initialFlag)
local tbl
if switchFase == 1 then
tbl = vci.state.Get("Range")
else
tbl = vci.state.Get("Offset")
end
if switchFase == 1 then
vci.assets.SetText("PositionNameText", "出現範囲")
else
vci.assets.SetText("PositionNameText", "出現オフセット")
end
local text = "x : "..tbl[1].."
y : "..tbl[2].."
z : "..tbl[3]
vci.assets.SetText("PositionText", text)
if switchFlag then
vci.assets.SetText("SwitchText", "スイッチ中心")
vci.assets.GetTransform("Yajirushi").SetActive(true)
if not(vci.assets.GetTransform("Yajirushi").GetAnimation().IsPlaying()) then
vci.assets.GetTransform("Yajirushi").GetAnimation().Play(true)
end
else
vci.assets.SetText("SwitchText", "プレイヤー中心")
vci.assets.GetTransform("Yajirushi").SetActive(false)
end
if initialFlag then
vci.assets.SetTextAndFitFontSize("OwnerText", vci.vc.room.GetLocalPlayer().GetName(), 0, 1.8)
end
end
--- Grab中のテキスト数値更新処理
--- @param switchFase boolean @表示は「出現範囲」か「出現オフセット」か
--- @param preScl table @Grabする前のスケール
--- @return table @更新後の数値
function displayModule.textUpdateGrabbing(switchFase, preScl)
local nowScl = {
switchCollider.GetLocalScale().x,
switchCollider.GetLocalScale().y,
switchCollider.GetLocalScale().z
}
local tbl
if switchFase == 1 then
tbl = vci.state.Get("Range")
vci.assets.SetText("PositionNameText", "出現範囲")
else
tbl = vci.state.Get("Offset")
vci.assets.SetText("PositionNameText", "出現オフセット")
end
local nxtState = {}
local text = ""
for i = 1, 3 do
--現在値をベースに、スケール変更を加える
local num = tonumber(tbl[i]) + math.log(nowScl[i]/preScl[i])
--上限下限チェック
if num > max[switchFase][i] then
num = max[switchFase][i]
elseif num < min[switchFase][i] then
num = min[switchFase][i]
end
--四捨五入処理
nxtState[i] = tostring(shishagonyu(num, 0.01))
--0詰め処理
if #nxtState[i] == 1 then
nxtState[i] = nxtState[i]..".00"
elseif #nxtState[i] == 3 then
nxtState[i] = nxtState[i].."0"
end
--テキスト化処理
if i == 1 then
text = text.."x : "..nxtState[i].."
"
elseif i == 2 then
text = text.."y : "..nxtState[i].."
"
elseif i == 3 then
text = text.."z : "..nxtState[i].."
"
end
end
vci.assets.SetText("PositionText", text)
return nxtState
end
--- 落下基準点を切り替えた際の高さオフセット調整処理
--- @param switchFlag boolean @基準位置がスイッチかどうか。
--- @param switchFase boolean @表示は「出現範囲」か「出現オフセット」か
--- @param adjustHeight number @オフセット量
--- @return string @落下位置のオフセット値(高さ)
function displayModule.baseSwitchHeightAdjust(switchFlag, switchFase, adjustHeight)
local tbl = vci.state.Get("Offset")
--補正処理
if switchFlag then
tbl[2] = tbl[2] - adjustHeight
else
tbl[2] = tbl[2] + adjustHeight
end
--四捨五入処理
tbl[2] = tostring(shishagonyu(tbl[2], 0.01))
--0詰め処理
if tbl[2] == 1 then
tbl[2] = tbl[2]..".00"
elseif tbl[2] == 3 then
tbl[2] = tbl[2].."0"
end
if switchFase == 2 then
local text = ""
--テキスト化処理
for i = 1, 3 do
if i == 1 then
text = text.."x : "..tbl[i].."
"
elseif i == 2 then
text = text.."y : "..tbl[i].."
"
elseif i == 3 then
text = text.."z : "..tbl[i].."
"
end
end
vci.assets.SetText("PositionText", text)
end
return tbl[2]
end
return displayModule
local solidComment = {}
--パレットの開け閉めの状態管理
local openFlag = false
local openAnimationFlag = false
local openAnimationStartTime = 0
local closeAnimationFlag = false
local closeAnimationStartTime = 0
--カラーパレットのオブジェクト名
local colorNameTbl = {
"Gold",
"Default",
"Pink",
"Studio",
"Blue",
"Pastel",
"White"
}
--パレット関係のオブジェクト
local colorCollider = {}
local colorObj = {}
for i = 1, 7 do
colorCollider[i] = vci.assets.GetTransform("ColorCollider"..i)
colorObj[i] = vci.assets.GetTransform(colorNameTbl[i])
end
local paletteButtonCollider = vci.assets.GetTransform("PaletteButtonCollider")
local paletteButton = vci.assets.GetTransform("PaletteButton")
local selectMark = vci.assets.GetTransform("Circle")
--カラーパレット番号
local colorPaletteNum = 2
--パレットアニメーション
local paletteAnime = vci.assets.GetTransform("ButtonRoot").GetAnimation()
--カラーパレットTbl
local colorTbl = {}
--金色のカラーパレット
colorTbl[1] = {}
colorTbl[1][1] = Color.__new(0.75, 0.6, 0.08, 1)
colorTbl[1][2] = Color.__new(0.84, 0.7, 0.25, 1)
colorTbl[1][3] = Color.__new(0.9, 0.8, 0.45, 1)
colorTbl[1][4] = Color.__new(0.95, 0.8, 0.05, 1)
colorTbl[1][5] = Color.__new(0.95, 0.9, 0.65, 1)
--デフォルトのカラーパレット(スクリプト上はTable内を参照しない)
colorTbl[2] = {Color.black}
--ピンクのカラーパレット
colorTbl[3] = {}
colorTbl[3][1] = Color.__new(0.94, 0.27, 0.6, 1)
colorTbl[3][2] = Color.__new(0.95, 0.4, 0.5, 1)
colorTbl[3][3] = Color.__new(1, 0.5, 0.75, 1)
colorTbl[3][4] = Color.__new(1, 0.7, 0.8, 1)
colorTbl[3][5] = Color.__new(0.95, 0.8, 0.9, 1)
colorTbl[3][6] = Color.__new(1, 0.2, 0.5, 1)
colorTbl[3][7] = Color.__new(0.85, 0.35, 0.4, 1)
--スタジオのカラーパレット
colorTbl[4] = {}
colorTbl[4][1] = Color.__new(236,236,236,255)/255 --白色
colorTbl[4][2] = Color.__new(200,199,153,255)/255 --薄黄色
colorTbl[4][3] = Color.__new(234,224,5,255)/255 --黄色
colorTbl[4][4] = Color.__new(236,193,1,255)/255 --濃い黄色
colorTbl[4][5] = Color.__new(153,154,1,255)/255 --黄金色
colorTbl[4][6] = Color.__new(0,200,102,255)/255 --薄緑色
colorTbl[4][7] = Color.__new(2,236,1,255)/255 --緑色
colorTbl[4][8] = Color.__new(1,235,234,255)/255 --水色
colorTbl[4][9] = Color.__new(1,1,235,255)/255 --青色
colorTbl[4][10] = Color.__new(103,51,198,255)/255 --紫色
colorTbl[4][11] = Color.__new(193,1,236,255)/255 --パッションピンク
colorTbl[4][12] = Color.__new(235,132,133,255)/255 --ピンク
colorTbl[4][13] = Color.__new(235,1,2,255)/255 --赤色
colorTbl[4][14] = Color.__new(199,1,52,255)/255 --濃い赤色
colorTbl[4][15] = Color.__new(234,105,0,255)/255 --オレンジ
--ブルーのカラーパレット
colorTbl[5] = {}
colorTbl[5][1] = Color.__new(0.4, 0.8, 1, 1)
colorTbl[5][2] = Color.__new(0.65, 0.8, 1, 1)
colorTbl[5][3] = Color.__new(0.85, 0.9, 0.95, 1)
colorTbl[5][4] = Color.__new(0.2, 0.4, 0.7, 1)
colorTbl[5][5] = Color.__new(0.3, 0.36, 0.65, 1)
colorTbl[5][6] = Color.__new(0, 0.2, 0.6, 1)
colorTbl[5][7] = Color.__new(0, 0.38, 0.7, 1)
--パステルカラーのカラーパレット
colorTbl[6] = {}
colorTbl[6][1] = Color.__new(1, 0.5, 0.5, 1)
colorTbl[6][2] = Color.__new(1, 0.5, 0.75, 1)
colorTbl[6][3] = Color.__new(1, 0.5, 1, 1)
colorTbl[6][4] = Color.__new(0.75, 0.5, 1, 1)
colorTbl[6][5] = Color.__new(0.5, 0.5, 1, 1)
colorTbl[6][6] = Color.__new(0.5, 0.75, 1, 1)
colorTbl[6][7] = Color.__new(0.5, 1, 1, 1)
colorTbl[6][8] = Color.__new(0.5, 1, 0.75, 1)
colorTbl[6][9] = Color.__new(0.5, 1, 0.5, 1)
colorTbl[6][10] = Color.__new(0.75, 1, 0.5, 1)
colorTbl[6][11] = Color.__new(1, 1, 0.5, 1)
colorTbl[6][12] = Color.__new(1, 0.75, 0.5, 1)
--白のカラーパレット
colorTbl[7] = {}
colorTbl[7][1] = Color.white
colorTbl[7][2] = Color.white
--- カラーパレット番号に応じた、マテリアル設定処理
--- @param options table @立体コメントの設定値
--- @return table @マテリアル設定後の立体コメントの設定値
local function colorPatternOptionSetting(options)
if colorPaletteNum == 2 then
--デフォルト設定カラーなので、特に処理なし
return options
end
if colorPaletteNum == 1 then
options.mainMaterial.metallic = 0.8
options.mainMaterial.smoothness = 0.8
options.sideMaterial.metallic = 0.8
options.sideMaterial.smoothness = 0.8
end
local randomNum = math.random(#colorTbl[colorPaletteNum])
if colorPaletteNum == 4 then
--Unlitライクに見せるマテリアル設定
options.mainMaterial.color = Color.black
options.mainMaterial.emissionColor = colorTbl[colorPaletteNum][randomNum].linear
options.sideMaterial.color = Color.black
options.sideMaterial.emissionColor = (colorTbl[colorPaletteNum][randomNum]*0.7).linear
else
options.mainMaterial.color = colorTbl[colorPaletteNum][randomNum]
end
return options
end
--- 立体コメントの生成処理
--- @param pos Vector3 @立体コメントの生成位置
--- @param rot Quaternion @立体コメントの生成回転
--- @param scl number @立体コメントの大きさ
--- @param comment string @立体コメントの文字列
function solidComment.commentDrop(pos, rot, scl, comment)
local options = {
position = pos,
rotation = Quaternion.Euler(0,180,0)*rot,
scale = scl,
thickness = scl,
autoDeleteSeconds = 15,
fontType = ExportSolidCommentFontType.NotoSans,
animations = {
isSpawnAnimationEnabled = false
},
mainMaterial = {},
sideMaterial = {}
}
colorPatternOptionSetting(options)
--options = colorPatternOptionSetting(options)
vci.vc.room.solidComment.CreateSolidComment(comment, options)
end
--- 色選択コライダーのアクティブ切り替え
--- @param activeFlag boolean @コライダーのアクティブ・非アクティブ
local function colorColliderActiveSwitch(activeFlag)
for i = 1, 7 do
colorCollider[i].SetActive(activeFlag)
end
end
--- パレットオブジェクトの非アクティブ化
function solidComment.inactive()
vci.assets.GetTransform("ColorPalette").SetActive(false)
paletteButtonCollider.SetActive(false)
colorColliderActiveSwitch(false)
end
--- パレットスイッチコライダーのアクティブ・非アクティブ化処理
function solidComment.paletteSwitchActive(activeFlag)
paletteButtonCollider.SetActive(activeFlag)
end
--- 色選択用コライダーの移動処理
local function colorColliderTransform()
if not(openFlag) or openAnimationFlag then
return
end
if paletteButtonCollider.IsMine then
for i = 1, 7 do
colorCollider[i].SetPosition(colorObj[i].GetPosition())
colorCollider[i].SetRotation(colorObj[i].GetRotation())
end
end
end
--- 選択マークの位置更新処理
local function selectColorUpdate()
if openFlag then
selectMark.SetLocalPosition(vci.assets.GetTransform(colorNameTbl[colorPaletteNum]).GetLocalPosition())
selectMark.SetLocalScale(100*Vector3.one)
end
end
--- パレットのオープンアニメーション処理
local function openAnimation()
if openAnimationFlag then
if os.time() - openAnimationStartTime >= 2 then
colorColliderActiveSwitch(true)
openAnimationFlag = false
end
end
end
--- パレットのクローズアニメーション処理
local function closeAnimation()
if closeAnimationFlag then
if os.time() - closeAnimationStartTime >= 2 then
vci.assets.GetTransform("ColorPalette").SetActive(false)
for i = 1, #colorNameTbl do
colorObj[i].SetLocalScale(100*Vector3.one)
end
closeAnimationFlag = false
end
end
end
--- 初期化時のState読み込み処理
function solidComment.readState()
if vci.state.Get("ColorPalette") ~= nil then
colorPaletteNum = vci.state.Get("ColorPalette")
end
end
--- main.luaのupdateAllに置く処理
function solidComment.updateAll()
--オープンアニメーション処理
openAnimation()
--クローズアニメーション処理
closeAnimation()
--色選択用コライダーの移動処理
colorColliderTransform()
--パレットのスイッチコライダーの移動処理
paletteButtonCollider.SetPosition(paletteButton.GetPosition())
paletteButtonCollider.SetRotation(paletteButton.GetRotation())
end
--- main.luaのonUseに置く処理
function solidComment.onUse(use)
--パレットスイッチを押した際の処理
if use == "PaletteButtonCollider" then
if openAnimationFlag or closeAnimationFlag then
else
openFlag = not(openFlag)
if openFlag then
vci.assets.GetTransform("ColorPalette").SetActive(true)
selectColorUpdate()
openAnimationFlag = true
openAnimationStartTime = os.time()
paletteAnime.PlayFromName("OpenAnimation", false)
else
closeAnimationFlag = true
closeAnimationStartTime = os.time()
colorColliderActiveSwitch(false)
paletteAnime.PlayFromName("CloseAnimation", false)
end
end
end
--色選択用コライダーを押した際の処理
if use:sub(1, #"ColorCollider") == "ColorCollider" then
if openFlag and not(openAnimationFlag) then
colorPaletteNum = tonumber(use:sub(-1))
vci.state.Set("ColorPalette", colorPaletteNum)
selectColorUpdate()
end
end
end
--- main.luaのonTriggerEnterに置く処理
function solidComment.onTriggerEnter(item, collider)
--手が、色選択用コライダーに触れた際の処理
if collider == "HandPointMarker" then
local vibrationFlag = false
local colorTouchFlag = false
if item:sub(1, #"ColorCollider") == "ColorCollider" then
vibrationFlag = true
colorTouchFlag = true
end
if colorTouchFlag then
for i = 1, 7 do
if i == tonumber(item:sub(-1)) then
colorObj[i].SetLocalScale(120*Vector3.one)
else
colorObj[i].SetLocalScale(100*Vector3.one)
end
end
end
if vibrationFlag then
vci.assets.HapticPulseOnTouchingController(item, 1, 0.1)
end
end
end
--- main.luaのonTriggerEnterに置く処理
function solidComment.onTriggerExit(item, collider)
--手が、色選択用コライダーから離れた際の処理
if collider == "HandPointMarker" then
if item:sub(1, #"ColorCollider") == "ColorCollider" then
colorObj[tonumber(item:sub(-1))].SetLocalScale(100*Vector3.one)
end
end
end
return solidComment