Skip to content

Commit

Permalink
Add FrameDuration parameter to Segments
Browse files Browse the repository at this point in the history
- Added a "FrameDuration" parameter to segments, which can be used to override the default flash rate (https://github.com/photonle/Photon-v2/wiki/Components#frameduration)

- Fixed texture issue with SOS Observe

- Misc workflow improvements
  • Loading branch information
ischmal committed Feb 18, 2024
1 parent 92433dc commit 5756094
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 51 deletions.
1 change: 1 addition & 0 deletions .annotations/photon-v2.lua
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ PhotonMaterial = PhotonMaterial
---@field Siren string Default siren name.

---@class PhotonLibraryComponentSegment
---@field FrameDuration? number Overrides the default duration of each frame. (In seconds.)
---@field Frames table<number, string | table>
---@field Sequences table<string, table<integer, integer>>

Expand Down
12 changes: 12 additions & 0 deletions lua/entities/photon_controller/cl_init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ function ENT:Initialize()
self.NextFrameTime = RealTime() + self.FrameDuration
self:InitializeShared()
self:DoInitializationStandby()
self.CurrentPulseComponents = {}
-- addTestEquipment(self)
end

Expand Down Expand Up @@ -96,6 +97,16 @@ function ENT:DoNextFrame()
end
end

function ENT:DoPulse()
if ( self.RebuildPulseComponents ) then self:UpdatePulseComponentArray() end
for i=1, #self.CurrentPulseComponents do
-- if ( self.CurrentPulseComponents[i].Pulse ) then
-- print(tostring(self.CurrentPulseComponents[i]))
self.CurrentPulseComponents[i]:Pulse()
-- end
end
end

---@diagnostic disable-next-line: duplicate-set-field
function ENT:Think()
if (not self.IsSuspended) then
Expand All @@ -111,6 +122,7 @@ function ENT:Think()
if (not self.IsSuspended) then
-- print("invalidating bone cache")
-- self:GetParent():InvalidateBoneCache()
self:DoPulse()
if (self.FrameCountEnabled and (self.NextFrameTime) <= RealTime() and ( not PHOTON2_FREEZE )) then
self:DoNextFrame()
end
Expand Down
32 changes: 31 additions & 1 deletion lua/entities/photon_controller/shared.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
---@field DoHardReload boolean (Internal) Triggers a hard reload on the next tick.
---@field DrawController boolean If the Photon Controller model should be visible.
---@field SyncAttachedParentSubMaterials boolean SGM attachment framework compatability.
---@field CurrentPulseComponents table<PhotonLightingComponent> (Internal) Array of components actively listening to controller pulse cycle.
---@field RebuildPulseComponents boolean (Internal) Triggers rebuild of all components that need to be on the pulse schedule.
ENT = ENT

local info, warn = Photon2.Debug.Declare( "Controller" )
Expand Down Expand Up @@ -253,7 +255,10 @@ function ENT:SetChannelMode( channel, state )
self:SetNW2String( "Photon2:CS:" .. channel, string.upper(state) )

if CLIENT then
self:OnChannelModeChanged( channel, state, oldState )
-- this line may be necessary for client prediction but it's doing some really weird shit
if ( not game.SinglePlayer() ) then
self:OnChannelModeChanged( channel, state, oldState )
end
Photon2.cl_Network.SetControllerChannelState( self, channel, state )
end

Expand Down Expand Up @@ -1034,18 +1039,26 @@ function ENT:OnChannelModeChanged( channel, newState, oldState )
oldState = oldState or "OFF"
-- print("Controller channel state changed. " .. tostring(self) .. " (" .. channel .. ") '" .. oldState .."' ==> '" .. newState .. "'")
self.CurrentModes[channel] = newState

local pulseComponents = {}

for id, component in pairs(self.Components) do
-- component:ApplyModeUpdate()
component:SetChannelMode( channel, newState, oldState )
if ( component.AcceptControllerPulse ) then pulseComponents[#pulseComponents+1] = component end
end
for id, virtualComponent in pairs( self.VirtualComponents ) do
-- component:ApplyModeUpdate()
virtualComponent:SetChannelMode( channel, newState, oldState )
if ( virtualComponent.AcceptControllerPulse ) then pulseComponents[#pulseComponents+1] = virtualComponent end
end
for id, uiComponent in pairs( self.UIComponents ) do
-- component:ApplyModeUpdate()
uiComponent:SetChannelMode( channel, newState, oldState )
if ( uiComponent.AcceptControllerPulse ) then pulseComponents[#pulseComponents+1] = uiComponent end
end

self.CurrentPulseComponents = pulseComponents
end


Expand Down Expand Up @@ -1167,6 +1180,8 @@ function ENT:OnComponentReloaded( componentId )
-- self.DoHardReload = true
-- end

self:UpdatePulseComponentArray()

self.LastReloadFailed = false
end

Expand Down Expand Up @@ -1226,4 +1241,19 @@ end
function ENT:GetSirenSelection( number )
if ( not self.CurrentProfile or not self.CurrentProfile.Siren ) then return nil end
return self.CurrentProfile.Siren[number]
end

function ENT:UpdatePulseComponentArray()
local result = {}
for i=1, #self.ComponentArray do
if( self.ComponentArray[i].AcceptControllerPulse ) then result[#result+1] = self.ComponentArray[i] end
end
for i=1, #self.VirtualComponentArray do
if( self.VirtualComponentArray[i].AcceptControllerPulse ) then result[#result+1] = self.VirtualComponentArray[i] end
end
for i=1, #self.UIComponentArray do
if( self.UIComponentArray[i].AcceptControllerPulse ) then result[#result+1] = self.UIComponentArray[i] end
end
self.CurrentPulseComponents = result
self.RebuildPulseComponents = false
end
2 changes: 2 additions & 0 deletions lua/photon-v2/exlib/sh_exmeta.lua
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ function exmeta.LoadFile(filename, tableName, erase)
if NAME == nil then error("[EXMeta] Global NAME must be defined. If it is, verify that the filepath is correct.") end
exmeta.LoadTable(NAME, BASE, _G[tableName], erase)
NAME, BASE, _G[tableName] = _NAME, _BASE, _META

Photon2.Util.ReloadAllControllers()
end

---@param name string
Expand Down
8 changes: 7 additions & 1 deletion lua/photon-v2/library/components/photon_sos_observe.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ COMPONENT.Model = "models/schmal/sos_observe.mdl"
COMPONENT.Templates = {
["Mesh"] = {
Model = {
Model = "models/schmal/sos_observe.mdl"
Model = "models/schmal/sos_observe.mdl",
States = {
-- R = {
-- DrawColor = PhotonColor( 255, 0, 0 ),
-- BloomColor = PhotonColor( 255, 0, 0 )
-- }
}
}
},
["DynamicLight"] = {
Expand Down
61 changes: 52 additions & 9 deletions lua/photon-v2/meta/lighting_component.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,17 @@ local print = Photon2.Debug.Print
---@field InputPriorities table<string, integer>
---@field CurrentModes table<string, string>
---@field ActiveSequences table<PhotonSequence, boolean>
---@field UseControllerTiming boolean (Default = `true`) When true, flash/sequence timing is managed by the Controller. Set to `false` if unsynchronized flashing is desired.
---@field ActiveIndependentSequences table<PhotonSequence, boolean>
---@field ActiveDependentSequences table<PhotonSequence, boolean>
---@field StateMap table<integer, string[]>
---@field InputActions table<string, string[]>
---@field ElementGroups table<string, integer[]>
---@field UseControllerModes boolean If true, the component will use its controller's CurrentModes table. If false, it will manage its own (required for Virtual InputActions).
---@field Phase string
---@field FrameDuration number
---@field AcceptControllerPulse boolean (Internal)
---@field AcceptControllerTiming boolean (Internal)
---@field Synchronized boolean If true, the component will synchronize with the controller's frame schedule (can be overridden by segments or sequences).
local Component = exmeta.New()

local Builder = Photon2.ComponentBuilder
Expand All @@ -32,6 +37,7 @@ Component.UseControllerModes = true
Component.IsPhotonLightingComponent = true
Component.InputPriorities = PhotonBaseEntity.DefaultInputPriorities


Component.ClassMap = {
Default = "PhotonLightingComponent",
Siren = "PhotonSirenComponent"
Expand Down Expand Up @@ -498,6 +504,8 @@ function Component:Initialize( ent, controller )
component.Elements = {}
component.Segments = {}
component.ActiveSequences = {}
component.ActiveIndependentSequences = {}
component.ActiveDependentSequences = {}

-- Process light table
for key, light in pairs(self.Elements) do
Expand All @@ -512,7 +520,6 @@ function Component:Initialize( ent, controller )
return component
end


function Component:OnScaleChange( newScale, oldScale )
for key, light in pairs(self.Elements) do
if (light.SetLightScale) then
Expand All @@ -521,6 +528,20 @@ function Component:OnScaleChange( newScale, oldScale )
end
end

function Component:Pulse()
local frameChange = false

for sequence, _ in pairs( self.ActiveIndependentSequences ) do
if ( sequence:OnPulse() ) then frameChange = true end
end

if ( frameChange ) then
for i=1, #self.Elements do
self.Elements[i]:UpdateState()
end
end
end

function Component:ApplyModeUpdate()


Expand Down Expand Up @@ -555,11 +576,19 @@ function Component:ApplyModeUpdate()

end

local acceptControllerPulse = false
for name, segment in pairs( self.Segments ) do
segment:ApplyModeUpdate()
local sequence = segment:ApplyModeUpdate()
if ( sequence and sequence.AcceptControllerPulse ) then
acceptControllerPulse = true
self.PhotonController.RebuildPulseComponents = true
end
end

self.AcceptControllerPulse = acceptControllerPulse

-- self:UpdateSegmentLightControl()
self:FrameTick()
self:FrameTick( true )
-- print("\t\tVirtual Outputs table:")
-- PrintTable( virtualOutputs )
-- print("\t\tInput table:")
Expand Down Expand Up @@ -589,7 +618,13 @@ end
function Component:RegisterActiveSequence( segmentName, sequence )
-- local sequence = self.Segments[segmentName].Sequences[sequence]
-- printf("Adding sequence [%s]", sequence.Name)
self.ActiveSequences[sequence] = sequence
self.ActiveSequences[sequence] = true

if ( sequence.AcceptControllerPulse ) then
self.ActiveIndependentSequences[sequence] = true
else
self.ActiveDependentSequences[sequence] = true
end
end


Expand All @@ -598,17 +633,25 @@ end
function Component:RemoveActiveSequence( segmentName, sequence)
-- printf("Removing sequence [%s]", sequence.Name)
self.ActiveSequences[sequence] = nil
self.ActiveIndependentSequences[sequence] = nil
self.ActiveDependentSequences[sequence] = nil
end

function Component:FrameTick()
function Component:FrameTick( all )

-- for segmentName, segment in pairs( self.Segments ) do
-- segment:IncrementFrame( self.PhotonController.Frame )
-- end

for sequence, _ in pairs( self.ActiveSequences ) do
sequence:IncrementFrame( self.PhotonController.Frame )
if ( all ) then
for sequence, _ in pairs( self.ActiveSequences ) do
sequence:IncrementFrame( self.PhotonController.Frame, true )
end
else
for sequence, _ in pairs( self.ActiveDependentSequences ) do
sequence:IncrementFrame( self.PhotonController.Frame, false )
end
end


for i=1, #self.Elements do
self.Elements[i]:UpdateState()
Expand Down
25 changes: 14 additions & 11 deletions lua/photon-v2/meta/lighting_segment.lua
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,19 @@ local printf = Photon2.Debug.PrintF
---@field InitializedFrames table<integer, table<PhotonElement, string>>
---@field QuickInputs table
---@field Lights table Points to Component.Elements
---@field FrameDuration number
---@field Synchronized boolean If true, the segment will use the controller's rolling frame index to always keep it synchronized.
local Segment = exmeta.New()

Segment.Inputs = {}
Segment.InputPriorities = {}
Segment.Count = 0
Segment.FrameDuration = 0.64
Segment.LastFrameTime = 0
Segment.Synchronized = false
-- Segment.InputPriorities = PhotonBaseEntity.DefaultInputPriorities

-- On compile
---@param segmentData any
---@param segmentData table
---@param lightGroups table<string, integer[]>
---@return PhotonElementingSegment
function Segment.New( name, segmentData, lightGroups, componentInputPriorities )
Expand All @@ -49,6 +51,8 @@ function Segment.New( name, segmentData, lightGroups, componentInputPriorities )
QuickInputs = {},
InputActions = {},
InputPriorities = setmetatable( segmentData.InputPriorities or {}, { __index = componentInputPriorities } ),
Synchronized = segmentData.Synchronized,
FrameDuration = segmentData.FrameDuration
}

setmetatable( segment, { __index = PhotonElementingSegment } )
Expand Down Expand Up @@ -308,9 +312,11 @@ function Segment:Initialize( componentInstance )
StateMap = componentInstance.StateMap,
Sequences = {},
InitializedFrames = {},
InputActions = {}
InputActions = {},
FrameDuration = self.FrameDuration or componentInstance.FrameDuration
}

-- print("Frame duration: " .. tostring(segment.FrameDuration))
setmetatable( segment, { __index = self } )

-- Setup frames
Expand All @@ -336,20 +342,16 @@ function Segment:Initialize( componentInstance )
end
end

-- -- Setup sequences
-- for sequenceName, sequence in pairs( self.Sequences ) do
-- error("Deprecated...")
-- -- printf( "Initializing sequence [%s]", sequenceName )
-- -- segment.Sequences[sequenceName] = sequence:Initialize( segment )
-- end

-- Setup inputs (new/revised sequences)
for channelMode, sequenceData in pairs( self.InputActions ) do
-- printf( "Initializing input sequence from channel mode [%s]", channelMode )
if ( not self.Sequences[sequenceData.Sequence] ) then
error( "Sequence [" .. tostring( sequenceData.Sequence ) .."] does not exist." )
end
segment.Sequences[sequenceData.Sequence] = self.Sequences[sequenceData.Sequence]:Initialize( sequenceData.Sequence, segment, sequenceData.Priority, sequenceData.Rank )
if ( segment.Sequences[sequenceData.Sequence].AcceptControllerPulse ) then
segment.AcceptPulse = true
end
end

segment:ApplyModeUpdate()
Expand Down Expand Up @@ -500,7 +502,7 @@ function Segment:ApplyModeUpdate()
-- printf( "CurrentPriorityScore: %s", self.CurrentPriorityScore )

-- Do nothing if active mode hasn't changed
if ( newMode == self.ActivePattern ) then return end
if ( newMode == self.ActivePattern ) then return self:GetCurrentSequence() end

-- self:DeactivateSequences()
self:DectivateCurrentSequence()
Expand All @@ -511,6 +513,7 @@ function Segment:ApplyModeUpdate()
self:ActivateCurrentSequence()
-- Turn lights back on
-- self:ActivateSequences()
return self:GetCurrentSequence()
end


Expand Down
Loading

0 comments on commit 5756094

Please sign in to comment.