Language:

サイドバー

バーチャルキャスト公式Wiki

メニュー

Steam版

デバイス

アセット

配信

その他

リリース情報

デベロッパー向け


開発環境

GLB

vci:sample:oscapi:commentdrop

立体コメント落下(わんコメ対応)

VirtualCast公式わんコメOSCプラグインでYouTube・ニコニコ生放送のコメントを受信して立体コメントを落下させるVCIのサンプルです。


サンプルデータ

Unitypackage

コンポーネント設定

VCI Object

VCIスクリプト

main.lua
--------------------------------------------------------------
---立体コメント落下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
planeKunDisplay.lua
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 = "<line-height=3.3>x : "..tbl[1].."<br>y : "..tbl[2].."<br>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 = "<line-height=3.3>"
    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].."<br>"
        elseif i == 2 then
            text = text.."y : "..nxtState[i].."<br>"
        elseif i == 3 then
            text = text.."z : "..nxtState[i].."<br>"
        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 = "<line-height=3.3>"
        --テキスト化処理
        for i = 1, 3 do
            if i == 1 then
                text = text.."x : "..tbl[i].."<br>"
            elseif i == 2 then
                text = text.."y : "..tbl[i].."<br>"
            elseif i == 3 then
                text = text.."z : "..tbl[i].."<br>"
            end
        end
        vci.assets.SetText("PositionText", text)
    end
    return tbl[2]
end
 
return displayModule
SolidComment.lua
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
vci/sample/oscapi/commentdrop.txt · 最終更新: 2025/06/26 15:35 by pastatto

ページ用ツール