-- Zones
Num_zones = 0
Zones = {}
--[[ Format for Zones
EDITOR DATA
.UID -- Unique ID (used by code)
.index -- Number (constant, should not change after init)
.time_start -- Starting time
.time_end -- Ending time
.solid -- Base object: solid fill (can be a gradient, see blend_next below)
.lock -- Base object: export lock icon (can be locked/unlocked, for display only)
.splitter -- Base object: splitter for zone (after current zone, disabled for last zone)
.text -- Base object: text for time display
.inactive -- Flag for whether the camera position can be edited (always true on all but one zone)
.highlight -- Flag for whether the current zone is selected (by the timeline marker)
.blend_next -- Flag for whether the next zone's type is set to Blend (affects the zone's solid image)
.x .y .w .h -- Coordinates/sizes for the zone (anchored left-center)
.right -- Final coordinates for right side of the zone (including the splitter), used in alignment
]]-- Zones
local MAX_ZONES = 32
-- The timeline object that handles mouse movements
Timeline_bg = {}
-- Marker objects
Marker_timeline = {}
Marker_playback = {}
Marker_select = {}
-- Marker subobjects (shouldn't need to access from outside this file)
local Mtl_text = nil
local Mtl_text_bg = nil
local Mtl_prev = nil
local Mtl_next = nil
local Mtl_bg_prev = nil
local Mtl_bg_next = nil
local Mpb_text = nil
local Mpb_text_bg = nil
local Mpb_play_to_arrow = nil
local Mpb_play_to_end = nil
local Mpb_play_to_line = nil
-- General timeline properties
Timeline_time_end = 30
Marker_time_timeline = 0
Marker_time_playback = 0
Marker_time_playback_goal = -1
-- State of playback/etc
Playback_disabled = false
Rewinding = false
-- Other flags/properties
Dragging_splitter = false
Drag_splitter_id = 0
-- Base elements
local Base_zone_solid = nil
local Base_zone_lock = nil
local Base_zone_splitter = nil
local Base_zone_text = nil
-- Color defines
local COLOR_TEXT_NORMAL = {R=160/255, G=160/255, B=160/255}
local COLOR_TEXT_HIGHLIGHT = {R=0/255, G=0/255, B=0/255}
local COLOR_TEXT_INACTIVE_NORMAL = {R=50/255, G=50/255, B=50/255}
local COLOR_TEXT_INACTIVE_HIGHLIGHT = {R=118/255, G=0/255, B=157/255}
local COLOR_SOLID_NORMAL = {R=0/255, G=0/255, B=0/255}
local COLOR_SOLID_HIGHLIGHT = {R=148/255, G=0/255, B=197/255}
local COLOR_LOCK_NORMAL = {R=60/255, G=60/255, B=60/255}
local COLOR_LOCK_HIGHLIGHT = {R=118/255, G=0/255, B=157/255}
local COLOR_SPLITTER_NORMAL = {R=60/255, G=0/255, B=80/255}
local COLOR_SPLITTER_HIGHLIGHT = {R=178/255, G=0/255, B=237/255}
-- Size defines
local TIMELINE_WIDTH = 1120
local TIMELINE_HEIGHT = 28
local TIMELINE_X = 640
if vint_is_std_res() then
TIMELINE_WIDTH = TIMELINE_WIDTH * 0.75
TIMELINE_X = TIMELINE_X * 0.75
end
local TIMELINE_Y = 60
local TIMELINE_BORDER = 0
local SPLITTER_WIDTH = 4
local ZONE_MIN_WIDTH = 2
local TIMELINE_LEFT -- Set in init
local TIMELINE_RIGHT -- Set in init
-- Minimum time for a zone when resizing
local ZONE_MIN_TIME = 0.05
function cinema_clip_editor_timeline_init()
-- Initialize the background element
Timeline_bg = Vdo_base_object:new("timeline_bg", 0, Cinema_clip_editor_doc_handle)
Timeline_bg:set_actual_size(TIMELINE_WIDTH, TIMELINE_HEIGHT)
Timeline_bg:set_anchor(TIMELINE_X, TIMELINE_Y)
TIMELINE_LEFT = TIMELINE_X - TIMELINE_WIDTH * 0.5 + TIMELINE_BORDER * 0.5
TIMELINE_RIGHT = TIMELINE_X + TIMELINE_WIDTH * 0.5 - TIMELINE_BORDER * 0.5
-- Get the marker objects
Marker_select = Vdo_base_object:new("timeline_carat", 0, Cinema_clip_editor_doc_handle)
Marker_timeline = Vdo_base_object:new("marker_timeline_grp", 0, Cinema_clip_editor_doc_handle)
Mtl_text = Vdo_base_object:new("mtl_text", 0, Cinema_clip_editor_doc_handle)
Mtl_text_bg = Vdo_base_object:new("mtl_bg", 0, Cinema_clip_editor_doc_handle)
Mtl_prev = Vdo_base_object:new("mtl_arrow_left", 0, Cinema_clip_editor_doc_handle)
Mtl_next = Vdo_base_object:new("mtl_arrow_right", 0, Cinema_clip_editor_doc_handle)
Mtl_bg_prev = Vdo_base_object:new("mtl_arrow_bg_left", 0, Cinema_clip_editor_doc_handle)
Mtl_bg_next = Vdo_base_object:new("mtl_arrow_bg_right", 0, Cinema_clip_editor_doc_handle)
Marker_playback = Vdo_base_object:new("marker_playback_grp", 0, Cinema_clip_editor_doc_handle)
Mpb_text = Vdo_base_object:new("mpb_text", 0, Cinema_clip_editor_doc_handle)
Mpb_text_bg = Vdo_base_object:new("mpb_bg", 0, Cinema_clip_editor_doc_handle)
Mpb_play_to_arrow = Vdo_base_object:new("mpb_play_to_arrow", 0, Cinema_clip_editor_doc_handle)
Mpb_play_to_end = Vdo_base_object:new("mpb_play_to_line", 0, Cinema_clip_editor_doc_handle)
Mpb_play_to_line = Vdo_base_object:new("mpb_play_to_end", 0, Cinema_clip_editor_doc_handle)
-- Get the base objects
Base_zone_solid = Vdo_base_object:new("zone_solid", 0, Cinema_clip_editor_doc_handle)
Base_zone_lock = Vdo_base_object:new("zone_lock", 0, Cinema_clip_editor_doc_handle)
Base_zone_splitter = Vdo_base_object:new("zone_splitter", 0, Cinema_clip_editor_doc_handle)
Base_zone_text = Vdo_base_object:new("zone_text", 0, Cinema_clip_editor_doc_handle)
-- Fill options (updates Timeline_time_end)
vint_dataresponder_request("cinema_editor_dr", "cinema_clip_editor_update_options", 0)
-- Set up the default zone data
for i = 1, MAX_ZONES do
Zones[i] = {}
cinema_clip_editor_zone_init(Zones[i], i)
end
Num_zones = 0
cinema_clip_editor_load_zones()
-- Reset marker objects
cinema_clip_editor_timeline_marker_set(TIMELINE_LEFT)
cinema_clip_editor_zone_update_highlight()
cinema_clip_editor_playback_marker_set(0)
-- Hide base objects
Base_zone_solid:set_visible(false)
Base_zone_lock:set_visible(false)
Base_zone_splitter:set_visible(false)
Base_zone_text:set_visible(false)
-- Subscribe to playback marker updates
vint_dataitem_add_subscription("playback_caret_di", "update", "cinema_clip_editor_playback_marker_update_di")
end
-- Update the playback marker from code
function cinema_clip_editor_playback_marker_update_di(di_h)
local marker_time = vint_dataitem_get(di_h)
cinema_clip_editor_playback_marker_set(marker_time)
if CCE_option_beginner_mode == true then
cinema_clip_editor_timeline_marker_set_time(marker_time)
end
-- Set play/pause buttons to disabled if the marker is done
if marker_time >= Timeline_time_end then
cinema_clip_editor_disable_play_pause()
end
end
function cinema_clip_editor_disable_play_pause()
if Rewinding == false then
CCE_free_buttons[BTN_FREE_PAUSE].button:set_inactive()
CCE_free_buttons[BTN_FREE_PLAY_SLOW].button:set_inactive()
CCE_free_buttons[BTN_FREE_PLAY].button:set_inactive()
CCE_free_buttons[BTN_FREE_PLAY_FAST].button:set_inactive()
Playback_disabled = true
end
end
function cinema_clip_editor_load_zones()
-- Get zones from the game, if they exist
vint_dataresponder_request("camera_zone_dr", "cinema_clip_editor_get_zones", MAX_ZONES)
-- No zones, so create one
if Num_zones == 0 then
-- Create the default zone
Zones[1].UID = cinema_editor_create_camera_zone(0.0)
Num_zones = 1
-- Set up data responder query for default zone
vint_dataresponder_request("camera_zone_dr", "cinema_clip_editor_update_zone", 1, Zones[1].UID)
end
cinema_clip_editor_zone_update_times()
cinema_clip_editor_zone_update_all()
end
function cinema_clip_editor_get_zones(uid, start, z_type, mode, desc, dof_mode, x_lock, slomo, fov, fov_bl, tilt, tilt_bl, hcam, hcam_bl, ddist, ddist_bl, dfocal, dfocal_bl, pos_bl, rot_bl, slomo_bl)
-- Check if this zone id already exists
for i = 1, Num_zones do
if Zones[i].UID == uid then
return
end
end
-- Check if we support this many zones
if Num_zones == MAX_ZONES then
return
end
Num_zones = Num_zones + 1
local zone = Zones[Num_zones]
zone.UID = uid
zone.time_start = start
zone.time_end = Timeline_time_end
zone.blend_next = false
-- And now the rest of the data
zone.zone_type = z_type
zone.camera_mode = mode
zone.dof_mode = dof_mode
zone.export_lock = x_lock
zone.slow_mo = slomo
zone.slow_mo_blend = slomo_bl -- Added later, so it comes after pos_bl in the parameters
zone.fov = fov
zone.fov_blend = fov_bl
zone.tilt = tilt
zone.tilt_blend = tilt_bl
zone.handycam = hcam
zone.handycam_blend = hcam_bl
zone.dof_dist = ddist
zone.dof_dist_blend = ddist_bl
zone.dof_focal = dfocal
zone.dof_focal_blend = dfocal_bl
zone.camera_blend = pos_bl -- This should always be the same as rot_bl
end
-- Update the zone (data responder)
function cinema_clip_editor_update_zone(uid, start, z_type, mode, desc, dof_mode, x_lock, slomo, fov, fov_bl, tilt, tilt_bl, hcam, hcam_bl, ddist, ddist_bl, dfocal, dfocal_bl, pos_bl, rot_bl, slomo_bl)
-- Find the correct camera zone
local this_zone = -1
for i = 1, Num_zones do
if Zones[i].UID == uid then
this_zone = i
end
end
local i = this_zone
-- Update the zone data and visuals
if i > -1 then
-- Times and visual flags first
Zones[i].time_start = start
Zones[i].time_end = Timeline_time_end
Zones[i].blend_next = false
-- Update stuff that depends on the next zone (if valid)
if Num_zones > i then
Zones[i].time_end = Zones[i + 1].time_start
if Zones[i + 1].zone_type == 0 then
Zones[i].blend_next = false
else
Zones[i].blend_next = true
end
end
-- And now the rest of the data
Zones[i].zone_type = z_type
Zones[i].camera_mode = mode
Zones[i].dof_mode = dof_mode
Zones[i].export_lock = x_lock
Zones[i].slow_mo = slomo
Zones[i].slow_mo_blend = slomo_bl -- Added later, so it comes after pos_bl in the parameters
Zones[i].fov = fov
Zones[i].fov_blend = fov_bl
Zones[i].tilt = tilt
Zones[i].tilt_blend = tilt_bl
Zones[i].handycam = hcam
Zones[i].handycam_blend = hcam_bl
Zones[i].dof_dist = ddist
Zones[i].dof_dist_blend = ddist_bl
Zones[i].dof_focal = dfocal
Zones[i].dof_focal_blend = dfocal_bl
Zones[i].camera_blend = pos_bl -- This should always be the same as rot_bl
end
end
-- Convert a number to a 2 decimal string
function cinema_clip_editor_num_to_string_2_decimal(num)
local whole = floor(num)
local decimal = floor(num * 100) - whole * 100
if decimal < 10 then
return (whole..".0"..decimal)
else
return (whole.."."..decimal)
end
end
-- Convert a number into one with two decimals (5.6423438 -> 5.64)
function cinema_clip_editor_num_round_2_decimal(num)
local whole = floor(num)
local decimal = floor(num * 100) - whole * 100
return whole + (decimal * 0.01)
end
--------------------------------------------------------------------------
-- Zone functions
--------------------------------------------------------------------------
-- Insert a new zone at zone_time (likely Marker_time_timeline)
function cinema_clip_editor_zone_insert(zone_time, copy_current)
-- Make sure we don't run out of zones
if Num_zones == MAX_ZONES then
return
end
-- Find which number we're inserting
local cur_zone = cinema_clip_editor_zone_highlight()
local zone_to_copy = cur_zone
if copy_current == false then
if cur_zone < Num_zones then
-- By the time we tell the game about this, it will be copied to the next slot
zone_to_copy = cur_zone + 2
end
end
-- Increase the number of zones
Num_zones = Num_zones + 1
-- Save the newest zone off
local temp_zone = {}
cinema_clip_editor_zone_copy(temp_zone, Zones[Num_zones])
-- Copy zone data (starting with the last one) to the prev index
for i = Num_zones, cur_zone + 2, -1 do
cinema_clip_editor_zone_copy(Zones[i], Zones[i - 1])
end
-- Copy temp zone data to the new zone
cinema_clip_editor_zone_copy(Zones[cur_zone + 1], temp_zone)
-- Set the times for the new zone
cinema_clip_editor_zone_set_times(Zones[cur_zone + 1], zone_time, Zones[cur_zone].time_end)
-- Tell the game about the new zone (copy the current or next one)
Zones[cur_zone + 1].UID = cinema_editor_create_camera_zone(zone_time, Zones[zone_to_copy].UID)
-- Get additional data from the game about the new zone
vint_dataresponder_request("camera_zone_dr", "cinema_clip_editor_update_zone", 1, Zones[cur_zone + 1].UID)
-- Cut down the previous zones end time
Zones[cur_zone].time_end = zone_time
-- Update everything
cinema_clip_editor_zone_update_all()
cinema_clip_editor_zone_update_highlight()
cinema_clip_editor_zone_update_inactive()
end
-- Deletes the currently highlighted zone
function cinema_clip_editor_zone_delete_current()
if Num_zones == 1 then
return
end
-- Find which number we're deleting
local cur_zone = cinema_clip_editor_zone_highlight()
-- Save off that zone
local temp_zone = {}
cinema_clip_editor_zone_copy(temp_zone, Zones[cur_zone])
-- Tell the game that the zone is deleted
vint_dataresponder_post("camera_zone_dr", "delete", Zones[cur_zone].UID)
-- Reduce the number of zones
Num_zones = Num_zones - 1
if cur_zone == 1 then
-- If we're deleting the first zone, change the start of the second zone
cinema_clip_editor_zone_set_times(Zones[2], Zones[1].time_start, Zones[2].time_end)
else
-- Otherwise change the end time of the previous zone
Zones[cur_zone - 1].time_end = Zones[cur_zone].time_end
end
-- Copy zone data to the previous index
for i = cur_zone, Num_zones do
cinema_clip_editor_zone_copy(Zones[i], Zones[i + 1])
end
-- Copy temp zone data to an invalid one (and hide that zone)
cinema_clip_editor_zone_copy(Zones[Num_zones + 1], temp_zone)
cinema_clip_editor_zone_set_visibility(Zones[Num_zones + 1], false)
-- Update everything
cinema_clip_editor_zone_update_all()
cinema_clip_editor_zone_update_highlight()
cinema_clip_editor_zone_update_inactive()
end
-- Copies editor data from the src to the dest
function cinema_clip_editor_zone_copy(zone_dest, zone_src)
zone_dest.solid = zone_src.solid
zone_dest.lock = zone_src.lock
zone_dest.splitter = zone_src.splitter
zone_dest.text = zone_src.text
zone_dest.inactive = zone_src.inactive
zone_dest.highlight = zone_src.highlight
zone_dest.cut = zone_src.cut
zone_dest.blend_next = zone_src.blend_next
zone_dest.x = zone_src.x
zone_dest.y = zone_src.y
zone_dest.w = zone_src.w
zone_dest.h = zone_src.h
zone_dest.right = zone_src.right
zone_dest.time_start = zone_src.time_start
zone_dest.time_end = zone_src.time_end
zone_dest.UID = zone_src.UID
zone_dest.zone_type = zone_src.zone_type
zone_dest.camera_mode = zone_src.camera_mode
zone_dest.dof_mode = zone_src.dof_mode
zone_dest.export_lock = zone_src.export_lock
zone_dest.slow_mo = zone_src.slow_mo
zone_dest.fov = zone_src.fov
zone_dest.fov_blend = zone_src.fov_blend
zone_dest.tilt = zone_src.tilt
zone_dest.tilt_blend = zone_src.tilt_blend
zone_dest.handycam = zone_src.handycam
zone_dest.handycam_blend = zone_src.handycam_blend
zone_dest.dof_dist = zone_src.dof_dist
zone_dest.dof_dist_blend = zone_src.dof_dist_blend
zone_dest.dof_focal = zone_src.dof_focal
zone_dest.dof_focal_blend = zone_src.dof_focal_blend
zone_dest.camera_blend = zone_src.camera_blend
end
-- Set the start and end times of a zone (and update the display text)
function cinema_clip_editor_zone_set_times(zone, t1, t2)
zone.time_start = t1
zone.time_end = t2
zone.text:set_text(cinema_clip_editor_num_to_string_2_decimal(t1))
end
-- Set the colors of a zone (based on its flags)
function cinema_clip_editor_zone_set_colors(zone)
if zone.inactive and zone.highlight then
zone.solid:set_color(COLOR_SOLID_HIGHLIGHT)
zone.text:set_color(COLOR_TEXT_INACTIVE_HIGHLIGHT)
zone.lock:set_color(COLOR_LOCK_HIGHLIGHT)
elseif zone.inactive and zone.highlight == false then
zone.solid:set_color(COLOR_SOLID_NORMAL)
zone.text:set_color(COLOR_TEXT_INACTIVE_NORMAL)
zone.lock:set_color(COLOR_LOCK_NORMAL)
elseif zone.inactive == false and zone.highlight == false then
zone.solid:set_color(COLOR_SOLID_NORMAL)
zone.text:set_color(COLOR_TEXT_NORMAL)
zone.lock:set_color(COLOR_LOCK_NORMAL)
elseif zone.inactive == false and zone.highlight then
zone.solid:set_color(COLOR_SOLID_HIGHLIGHT)
zone.text:set_color(COLOR_TEXT_HIGHLIGHT)
zone.lock:set_color(COLOR_LOCK_HIGHLIGHT)
end
end
-- Update the visuals of a zone in the timeline, speficially the images for blending and export lock
function cinema_clip_editor_zone_update_visuals(zone)
if zone.export_lock == 1 then
zone.lock:set_image("ui_pc_icon_locked")
else
zone.lock:set_image("ui_pc_icon_unlocked")
end
local w,h = zone.solid:get_actual_size()
if zone.blend_next then
zone.solid:set_image("ui_pc_gradient_256")
else
zone.solid:set_image("ui_blank")
end
zone.solid:set_actual_size(w, h)
end
-- Update the blend_next flag for all zones
function cinema_clip_editor_zone_update_blend_next()
for i = 1, Num_zones - 1 do
if Zones[i + 1].zone_type == 0 then
Zones[i].blend_next = false
else
Zones[i].blend_next = true
end
end
end
-- Initialize a zone's elements and relevant flags
function cinema_clip_editor_zone_init(zone, idx)
zone.UID = -1
zone.index = idx
zone.solid = Vdo_base_object:clone(Base_zone_solid.handle)
zone.lock = Vdo_base_object:clone(Base_zone_lock.handle)
zone.splitter = Vdo_base_object:clone(Base_zone_splitter.handle)
zone.text = Vdo_base_object:clone(Base_zone_text.handle)
zone.inactive = false
zone.highlight = false
zone.cut = true
zone.blend_next = false
zone.right = TIMELINE_RIGHT
zone.zone_type = 0
zone.camera_mode = 0
zone.dof_mode = 0
zone.export_lock = 1
zone.slow_mo = 0
zone.slow_mo_blend = 0
zone.fov = 50
zone.fov_blend = 0
zone.tilt = 0
zone.tilt_blend = 0
zone.handycam = 0
zone.handycam_blend = 0
zone.dof_dist = 50
zone.dof_dist_blend = 0
zone.dof_focal = 50
zone.dof_focal_blend = 0
zone.camera_blend = 0
cinema_clip_editor_zone_set_visibility(zone, false)
end
-- Set the visibility of a zone
function cinema_clip_editor_zone_set_visibility(zone, visible)
zone.solid:set_visible(visible)
zone.text:set_visible(visible)
zone.lock:set_visible(visible)
zone.splitter:set_visible(visible)
end
-- Resize the zone using its time_start and time_end
function cinema_clip_editor_zone_update_size(zone, last, prev_zone_right)
-- Calculate my coordinates and size
local frac_start = zone.time_start / Timeline_time_end
local frac_end = (zone.time_end - zone.time_start) / Timeline_time_end
local min_x = prev_zone_right or 0
zone.x = TIMELINE_LEFT + frac_start * (TIMELINE_WIDTH - TIMELINE_BORDER)
-- Make the zone start at the border of the previous zone (only a problem with really squished zones)
local prev_fix = 0
if zone.x < min_x then
prev_fix = min_x - zone.x
zone.x = min_x
end
zone.w = frac_end * (TIMELINE_WIDTH - TIMELINE_BORDER) - prev_fix
zone.y = TIMELINE_Y
zone.h = TIMELINE_HEIGHT - TIMELINE_BORDER
-- Reduce the width if this is not the last zone (to make room for the splitter)
if last == false then
zone.w = zone.w - SPLITTER_WIDTH
if zone.w < ZONE_MIN_WIDTH then
zone.w = ZONE_MIN_WIDTH
end
end
-- Arrange the elements
zone.solid:set_anchor(zone.x, zone.y)
zone.text:set_anchor(zone.x, zone.y)
zone.lock:set_anchor(zone.x + zone.w, zone.y)
zone.splitter:set_anchor(zone.x + zone.w, zone.y)
-- Resize the elements (scale them up, measure, and cap)
zone.solid:set_actual_size(zone.w, zone.h)
zone.text:set_scale(0.8, 0.8)
local temp_w, temp_h = zone.text:get_actual_size()
if temp_w > zone.w then
zone.text:set_actual_size(zone.w, temp_h)
end
zone.lock:set_scale(1.0, 1.0)
temp_w, temp_h = zone.lock:get_actual_size()
if temp_w > zone.w then
zone.lock:set_actual_size(zone.w, temp_h)
end
-- Save the right side coordinates (including splitter, even if it's turned off)
zone.right = zone.x + zone.w + SPLITTER_WIDTH
-- Show the splitter (as long as it's not the last zone)
if last then
zone.splitter:set_actual_size(0, 0)
else
zone.splitter:set_actual_size(SPLITTER_WIDTH, zone.h)
end
end
-- Move the current splitter and update the zones
function cinema_clip_editor_zone_splitter_move(zone_id, mouse_x)
-- Constrain the time to the current zone's start and next zone's end
local t = cinema_clip_editor_mouse_to_time(mouse_x)
if t < Zones[zone_id].time_start + ZONE_MIN_TIME then
t = Zones[zone_id].time_start + ZONE_MIN_TIME
elseif t > Zones[zone_id + 1].time_end - ZONE_MIN_TIME then
t = Zones[zone_id + 1].time_end - ZONE_MIN_TIME
end
t = cinema_clip_editor_num_round_2_decimal(t)
-- Set the start/end times for the zones
cinema_clip_editor_zone_set_times(Zones[zone_id], Zones[zone_id].time_start, t )
cinema_clip_editor_zone_set_times(Zones[zone_id + 1], t, Zones[zone_id + 1].time_end)
-- Let the code know about the new time
vint_dataresponder_post("camera_zone_dr", "set_time", Zones[zone_id + 1].UID, t)
cinema_clip_editor_zone_update_all()
cinema_clip_editor_zone_update_highlight()
cinema_clip_editor_zone_update_inactive()
end
-- Update all the zone times
function cinema_clip_editor_zone_update_times()
for i = 1, Num_zones - 1 do
cinema_clip_editor_zone_set_times(Zones[i], Zones[i].time_start, Zones[i + 1].time_start)
end
end
-- Resize all the zones (after calculating some required elements)
function cinema_clip_editor_zone_update_all()
local right = 0
local last = false
for i = 1, Num_zones do
if i > 1 then
right = Zones[i - 1].right
end
if i == Num_zones then
last = true
end
cinema_clip_editor_zone_update_size(Zones[i], last, right)
cinema_clip_editor_zone_set_visibility(Zones[i], true)
-- Data fixup/restrictions
-- First zone: can't be blend
if i == 1 then
Zones[i].zone_type = 0
end
-- Last zone: can't have blend_next
if i == Num_zones then
Zones[i].blend_next = false
end
-- Not last zone: update blend_next flag and other data if applicable
if Num_zones > i then
if Zones[i + 1].zone_type == 0 then
Zones[i].blend_next = false
else
Zones[i].blend_next = true
-- Copy some data from the current zone
Zones[i + 1].camera_mode = Zones[i].camera_mode
Zones[i + 1].export_lock = Zones[i].export_lock
Zones[i + 1].slow_mo = Zones[i].slow_mo
Zones[i + 1].dof_mode = Zones[i].dof_mode
end
end
cinema_clip_editor_zone_update_visuals(Zones[i])
end
end
-- Convert an X coordinate to a time
function cinema_clip_editor_mouse_to_time(mouse_x)
local frac = (mouse_x - TIMELINE_LEFT) / TIMELINE_WIDTH
local t = frac * Timeline_time_end
return t
end
-- Find the zone that should be highlighted and do it
function cinema_clip_editor_zone_update_highlight()
local used = false
-- Loop through all zones, find the one that has timeline marker, highlight it (and update the colors)
for i = 1, Num_zones do
if Zones[i].time_end > Marker_time_timeline and used == false then
Zones[i].highlight = true
used = true
else
Zones[i].highlight = false
end
cinema_clip_editor_zone_set_colors(Zones[i])
end
-- Make sure something is highlighted
if Num_zones > 0 then
if used == false then
Zones[Num_zones].highlight = true
cinema_clip_editor_zone_set_colors(Zones[Num_zones])
end
-- Update the properties dialog
local cur_zone = cinema_clip_editor_zone_get_current()
cinema_clip_editor_prop_dialog_fill_data(cur_zone)
end
end
-- Update the inactive flag for all zones (one will always be active)
function cinema_clip_editor_zone_update_inactive()
local used = false
-- Loop through all zones, find the one that has timeline marker, highlight it (and update the colors)
for i = 1, Num_zones do
if Zones[i].time_end > Marker_time_playback and used == false then
Zones[i].inactive = false
used = true
else
Zones[i].inactive = true
end
cinema_clip_editor_zone_set_colors(Zones[i])
end
-- Make sure something is active
if Num_zones > 0 then
if used == false then
Zones[Num_zones].inactive = false
cinema_clip_editor_zone_set_colors(Zones[Num_zones])
end
end
-- Adjust the play_to elements
-- Find the anchor and other measurements
local x, y = Marker_playback:get_anchor()
local w, h = Mpb_text_bg:get_actual_size()
-- Right side of the text bg
local min_x = w * 0.5
-- Get the x coordinate (Marker_playback-relative) of the zone border
local active_zone = cinema_clip_editor_zone_active()
local border_x = Zones[active_zone].right - x
-- Get the anchor of the arrow (Y value will be used below)
x, y = Mpb_play_to_arrow:get_anchor()
-- Find the actual location of the right side play_to elements
x = max(border_x, min_x + 12)
-- Move/resize the elements
Mpb_play_to_line:set_anchor(x, y)
Mpb_play_to_end:set_anchor(x, y)
Mpb_play_to_end:set_actual_size(x - min_x - 2, h)
end
-- Get the currently active zone id
function cinema_clip_editor_zone_active()
for i = 1, Num_zones do
if Zones[i].inactive == false then
return i
end
end
return 1
end
-- Get the currently highlighted zone id
function cinema_clip_editor_zone_highlight()
for i = 1, Num_zones do
if Zones[i].highlight == true then
return i
end
end
return 1
end
function cinema_clip_editor_zone_get_current()
local highlight = cinema_clip_editor_zone_highlight()
if highlight > 0 then
return Zones[highlight]
else
return nil
end
end
function cinema_clip_editor_zone_get_previous()
local highlight = cinema_clip_editor_zone_highlight()
if highlight - 1 > 0 then
return Zones[highlight - 1]
else
return nil
end
end
--------------------------------------------------------------------------
-- Mouse input functions
--------------------------------------------------------------------------
-- MOUSE OVERVIEW
-- Mouse_move_always: Highlighted the appropriate item (splitter), move the select marker
-- Mouse_drag: If highlighting splitter: Move the splitter (do not update highlight, set drag flag)
-- If highlighting zone: Update highlight, set timeline marker
-- Mouse_click: Set timeline marker
-- Mouse_drag_release: If dragging splitter, unset drag flag (else nothing)
-- Add mouse inputs
function cinema_clip_editor_timeline_add_mouse_inputs(input_tracker)
-- Timeline background (primary input)
input_tracker:add_mouse_input("mouse_down", "cinema_clip_editor_mouse_down_timeline", 0, Timeline_bg.handle)
input_tracker:add_mouse_input("mouse_click", "cinema_clip_editor_mouse_click_timeline", 0, Timeline_bg.handle)
input_tracker:add_mouse_input("mouse_drag", "cinema_clip_editor_mouse_drag_timeline", 0, Timeline_bg.handle)
input_tracker:add_mouse_input("mouse_drag_release", "cinema_clip_editor_mouse_drag_release_timeline", 0, Timeline_bg.handle)
input_tracker:add_mouse_input("mouse_move_always", "cinema_clip_editor_mouse_move_always_timeline", 0, Timeline_bg.handle)
-- Marker buttons
input_tracker:add_mouse_input("mouse_click", "cinema_clip_editor_mouse_click_playback_marker", 0, Mpb_play_to_arrow.handle)
input_tracker:add_mouse_input("mouse_move", "cinema_clip_editor_mouse_move_playback_marker", 0, Mpb_play_to_arrow.handle)
input_tracker:add_mouse_input("mouse_click", "cinema_clip_editor_mouse_click_timeline_marker_next", 0, Mtl_next.handle)
input_tracker:add_mouse_input("mouse_move", "cinema_clip_editor_mouse_move_timeline_marker_next", 0, Mtl_next.handle)
input_tracker:add_mouse_input("mouse_click", "cinema_clip_editor_mouse_click_timeline_marker_prev", 0, Mtl_prev.handle)
input_tracker:add_mouse_input("mouse_move", "cinema_clip_editor_mouse_move_timeline_marker_prev", 0, Mtl_prev.handle)
input_tracker:add_mouse_input("mouse_click", "cinema_clip_editor_mouse_click_timeline_marker", 0, Mtl_text_bg.handle)
input_tracker:add_mouse_input("mouse_move", "cinema_clip_editor_mouse_move_timeline_marker", 0, Mtl_text_bg.handle)
end
function cinema_clip_editor_convert_mouse_screen_coordinates(mouse_x, mouse_y)
local screen_w, screen_h = vint_get_screen_size()
if vint_is_std_res() then
if (screen_w / screen_h) < 1.333 then
local offset_x = (screen_h * 1.333 - screen_w) * 0.5
mouse_x = offset_x + mouse_x * ((screen_w / screen_h) / 1.333)
end
mouse_x = (mouse_x * 640 / screen_w) * 1.5
mouse_y = ((mouse_y - (screen_h - 480 * screen_w / 640) / 2) * 640 / screen_w) * 1.5
else
if (screen_w / screen_h) < 1.777 then
local offset_x = (screen_h * 1.777 - screen_w) * 0.5
mouse_x = offset_x + mouse_x * ((screen_w / screen_h) / 1.777)
end
mouse_x = (mouse_x * 1280 / screen_w)
mouse_y = ((mouse_y - (screen_h - 720 * screen_w / 1280) / 2) * 1280 / screen_w)
end
return mouse_x, mouse_y
end
-- Dummy event to make mouse_drag work
function cinema_clip_editor_mouse_click_timeline(event, target_handle, mouse_x, mouse_y)
end
-- When first pressing the mouse: Start dragging a splitter or update the timeline marker
function cinema_clip_editor_mouse_down_timeline(event, target_handle, mouse_x, mouse_y)
mouse_x, mouse_y = cinema_clip_editor_convert_mouse_screen_coordinates(mouse_x, mouse_y)
local splitter = cinema_clip_editor_mouse_select_splitter(mouse_x)
if splitter > 0 then
Drag_splitter_id = splitter
Dragging_splitter = true
else
cinema_clip_editor_timeline_marker_set(mouse_x)
cinema_clip_editor_zone_update_highlight()
Marker_select:set_visible(false)
end
end
-- When dragging the mouse: Move the current splitter or update the timeline marker
function cinema_clip_editor_mouse_drag_timeline(event, target_handle, mouse_x, mouse_y)
mouse_x, mouse_y = cinema_clip_editor_convert_mouse_screen_coordinates(mouse_x, mouse_y)
if Dragging_splitter == true then
cinema_clip_editor_zone_splitter_move(Drag_splitter_id, mouse_x)
else
cinema_clip_editor_timeline_marker_set(mouse_x)
cinema_clip_editor_zone_update_highlight()
Marker_select:set_visible(false)
end
end
function cinema_clip_editor_mouse_drag_release_timeline(event, target_handle, mouse_x, mouse_y)
mouse_x, mouse_y = cinema_clip_editor_convert_mouse_screen_coordinates(mouse_x, mouse_y)
if Dragging_splitter == true then
Dragging_splitter = false
end
end
-- When moving the mouse: Highlight a splitter or move the selection marker
function cinema_clip_editor_mouse_move_always_timeline(event, target_handle, mouse_x, mouse_y)
mouse_x, mouse_y = cinema_clip_editor_convert_mouse_screen_coordinates(mouse_x, mouse_y)
-- Is the mouse over a splitter
local splitter = cinema_clip_editor_mouse_select_splitter(mouse_x)
if splitter > 0 then
-- Highlight the splitter (and hide the selection marker)
cinema_clip_editor_splitter_highlight(splitter, true)
Marker_select:set_visible(false)
else
cinema_clip_editor_splitter_unhighlight_all()
-- Update the selection markers position (and make it visible)
Marker_select:set_anchor(mouse_x, TIMELINE_Y)
Marker_select:set_visible(true)
end
cinema_clip_editor_timeline_unhighlight_mini_buttons()
end
-- Returns the zone id of the splitter under the mouse (or 0 if none)
function cinema_clip_editor_mouse_select_splitter(mouse_x)
-- Don't scale mouse for resolution because it's scaled prior to this
-- Go thru zones, find which one we're in
local cur_zone = 0
for i = 1, Num_zones do
if mouse_x > Zones[i].x and mouse_x <= Zones[i].right then
cur_zone = i
end
end
-- Make sure we're in a zone (but not the last one, which has no splitter)
if cur_zone > 0 and cur_zone < Num_zones then
-- Check if the mouse is over the splitter
if mouse_x >= (Zones[cur_zone].right - SPLITTER_WIDTH) then
return cur_zone
end
end
return 0
end
-- Unhighlight all splitters
function cinema_clip_editor_splitter_unhighlight_all()
for i = 1, Num_zones do
cinema_clip_editor_splitter_highlight(i, false)
end
end
-- Highlight the given splitter (referenced by zone id)
function cinema_clip_editor_splitter_highlight(s_zone, highlight)
if highlight == true then
Zones[s_zone].splitter:set_color(COLOR_SPLITTER_HIGHLIGHT)
else
Zones[s_zone].splitter:set_color(COLOR_SPLITTER_NORMAL)
end
end
-- Called from other mouse_move events (in main cinema_clip_editor file)
function cinema_clip_editor_timeline_mouse_off()
Marker_select:set_visible(false)
cinema_clip_editor_timeline_unhighlight_mini_buttons()
end
-- Marker mini-button mouse functions
-- When clicking the marker's arrow button: Move the playback marker forward (sort of)
function cinema_clip_editor_mouse_click_playback_marker(event, target_handle)
if Playback_disabled == false then
Rewinding = false
cinema_clip_editor_playback_marker_jump()
end
end
-- When moving the mouse over the button: Highlight its elements
function cinema_clip_editor_mouse_move_playback_marker(event, target_handle)
if Playback_disabled == false then
cinema_clip_editor_timeline_unhighlight_mini_buttons()
cinema_clip_editor_double_highlight(true, Mpb_play_to_arrow, Mpb_play_to_end)
end
end
-- When clicking the marker's right arrow button: Move the timeline marker forward
function cinema_clip_editor_mouse_click_timeline_marker_next(event, target_handle)
cinema_clip_editor_timeline_marker_next()
end
-- When moving the mouse over the button: Highlight its elements
function cinema_clip_editor_mouse_move_timeline_marker_next(event, target_handle)
cinema_clip_editor_timeline_unhighlight_mini_buttons()
cinema_clip_editor_double_highlight(true, Mtl_next, Mtl_bg_next)
end
-- When clicking the marker's left arrow button: Move the timeline marker backward
function cinema_clip_editor_mouse_click_timeline_marker_prev(event, target_handle)
cinema_clip_editor_timeline_marker_prev()
end
-- When moving the mouse over the button: Highlight its elements
function cinema_clip_editor_mouse_move_timeline_marker_prev(event, target_handle)
cinema_clip_editor_timeline_unhighlight_mini_buttons()
cinema_clip_editor_double_highlight(true, Mtl_prev, Mtl_bg_prev)
end
-- When clicking the marker's time, open the basic dialog
function cinema_clip_editor_mouse_click_timeline_marker(event, target_handle)
local x, y = Marker_timeline:get_anchor()
cinema_clip_editor_dialog_camera_zone_slide(x)
end
-- When moving the mouse over the button: Highlight its elements
function cinema_clip_editor_mouse_move_timeline_marker(event, target_handle)
cinema_clip_editor_timeline_unhighlight_mini_buttons()
cinema_clip_editor_double_highlight(true, Mtl_text, Mtl_text_bg)
end
-- Remove highlighting from all the small marker buttons
function cinema_clip_editor_timeline_unhighlight_mini_buttons()
cinema_clip_editor_double_highlight(false, Mpb_play_to_arrow, Mpb_play_to_end)
cinema_clip_editor_double_highlight(false, Mtl_next, Mtl_bg_next)
cinema_clip_editor_double_highlight(false, Mtl_prev, Mtl_bg_prev)
cinema_clip_editor_double_highlight(false, Mtl_text, Mtl_text_bg)
end
-- Sets the img/bg colors based on the highlight (used for mini buttons)
function cinema_clip_editor_double_highlight(highlight, img, bg)
if highlight == true then
img:set_color(COLOR_TEXT_HIGHLIGHT)
bg:set_color(COLOR_SOLID_HIGHLIGHT)
else
img:set_color(COLOR_TEXT_NORMAL)
bg:set_color(COLOR_SOLID_NORMAL)
end
end
--------------------------------------------------------------------------
-- Marker functions
--------------------------------------------------------------------------
-- Set the timeline marker based on a screen value (can also just send 0 to reset it)
function cinema_clip_editor_timeline_marker_set(mouse_x)
local x = mouse_x
local min_x = TIMELINE_X - TIMELINE_WIDTH * 0.5 + TIMELINE_BORDER * 0.5
local max_x = TIMELINE_X + TIMELINE_WIDTH * 0.5 - TIMELINE_BORDER * 0.5
-- Limit x to the extents of the timeline
x = min(x, max_x)
x = max(x, min_x)
Marker_timeline:set_anchor(x, TIMELINE_Y + TIMELINE_HEIGHT * 0.5)
-- Translate the coordinates to a time, and set it
local frac = (x - min_x) / (max_x - min_x)
Marker_time_timeline = frac * Timeline_time_end
Mtl_text:set_text(cinema_clip_editor_num_to_string_2_decimal(Marker_time_timeline))
cinema_clip_editor_zone_update_highlight()
cinema_clip_editor_dialog_camera_zone_slide(x)
end
-- Sets the timeline marker using a time
function cinema_clip_editor_timeline_marker_set_time(t)
local frac = min(1, t / Timeline_time_end)
local x1 = TIMELINE_LEFT
local x2 = (TIMELINE_WIDTH - TIMELINE_BORDER) * frac
local x = x1 + x2
Marker_timeline:set_anchor(x, TIMELINE_Y + TIMELINE_HEIGHT * 0.5)
-- Set the text
Marker_time_timeline = min(t, Timeline_time_end)
Mtl_text:set_text(cinema_clip_editor_num_to_string_2_decimal(Marker_time_timeline))
cinema_clip_editor_zone_update_highlight()
cinema_clip_editor_dialog_camera_zone_slide(x)
end
-- Set the playback marker based on a time value
function cinema_clip_editor_playback_marker_set(t)
local frac = min(1, t / Timeline_time_end)
local x1 = TIMELINE_LEFT
local x2 = (TIMELINE_WIDTH - TIMELINE_BORDER) * frac
local x = x1 + x2
Marker_playback:set_anchor(x, TIMELINE_Y - TIMELINE_HEIGHT * 0.5)
-- Set the text
Marker_time_playback = min(t, Timeline_time_end)
Mpb_text:set_text(cinema_clip_editor_num_to_string_2_decimal(Marker_time_playback))
cinema_clip_editor_zone_update_inactive()
end
-- Set the playback goal time to the current zone's end time
function cinema_clip_editor_playback_marker_jump()
local active_zone = cinema_clip_editor_zone_active()
if active_zone == Num_zones then
Marker_time_playback_goal = Timeline_time_end
else
Marker_time_playback_goal = Zones[active_zone].time_end
end
vint_dataresponder_post("cinema_editor_dr", "play_to_time", Marker_time_playback_goal)
cinema_clip_editor_playback_buttons(true)
CCE_free_buttons[BTN_FREE_PAUSE].button:set_active()
end
-- Set the timeline marker to the end of the current zone (aka the beginning of the next zone)
function cinema_clip_editor_timeline_marker_next()
local highlight_zone = cinema_clip_editor_zone_highlight()
cinema_clip_editor_timeline_marker_set(Zones[highlight_zone].right + 0.1)
cinema_clip_editor_zone_update_highlight()
end
-- Set the timeline marker to the beginning of the current zone (or previous zone if at the beginning)
function cinema_clip_editor_timeline_marker_prev()
local highlight_zone = cinema_clip_editor_zone_highlight()
-- Check for being at the beginning of the current zone
if abs(Marker_time_timeline - Zones[highlight_zone].time_start) < 0.01 then
-- Go back a zone (if possible)
if highlight_zone > 1 then
highlight_zone = highlight_zone - 1
end
end
cinema_clip_editor_timeline_marker_set(Zones[highlight_zone].x + 0.1)
cinema_clip_editor_zone_update_highlight()
end