### Virtual Track Main Script Entry Point Source: https://context7.com/gorankovac/reascripts/llms.txt This Lua script serves as the main entry point for the Virtual Track functionality. It checks for required extensions, sets the interaction mode, and displays the version selection menu. Ensure JS_ReaScriptAPI >= 1.301 and ReaImGui are installed. ```lua -- Virtual Track main script entry point -- File: VirtualTrack/Virtual_track_Mouse.lua package.path = debug.getinfo(1, "S"):match ("[^\/]+$") .. "?.lua;" require("Modules/VTCommon") require("Modules/Utils") -- Check for required extensions (JS_ReaScriptAPI >= 1.301, ReaImGui) Check_Requirements() -- Set the Virtual Track mode to mouse-based interaction reaper.SetProjExtState(0, "VirtualTrack", "ONDEMAND_MODE", "mouse") local function Main() -- Get track data for on-demand version display local track_tbl = OnDemand() if not track_tbl then return end -- Show the version selection popup menu Show_menu(track_tbl) end -- Execute with crash handler for error reporting xpcall(Main, GetCrash()) ``` -------------------------------- ### Initialize ParanormalFX Router Source: https://context7.com/gorankovac/reascripts/llms.txt Initializes the ParanormalFX Router, checks for REAPER V7.11+ compatibility, loads the ImGui API, and sets up API wrappers for track and take FX functions. It also checks and installs third-party dependencies via ReaPack and creates an ImGui context. ```lua -- ParanormalFX Router initialization -- File: ParanormalFX/Sexan_ParaNormal_FX_Router.lua local r = reaper -- Require REAPER V7.11 or later if not r.GetAppVersion():match("^7%.%") then r.ShowMessageBox("This script requires Reaper V7", "WRONG REAPER VERSION", 0) return end -- Load ImGui API dofile(r.GetResourcePath() .. '/Scripts/ReaTeam Extensions/API/imgui.lua')('0.9.3') -- Build API wrappers for track and take FX functions local track_api = {} local take_api = {} for name, func in pairs(r) do local track_name = name:match('^TrackFX_(.+)$') local take_name = name:match('^TakeFX_(.+)$') if track_name then track_api[track_name] = func end if take_name then take_api[take_name] = func end end -- Additional API mappings take_api["CopyToTrack"] = r.TakeFX_CopyToTake take_api["GetFXEnvelope"] = r.TakeFX_GetEnvelope track_api["GetFXEnvelope"] = r.GetFXEnvelope -- Check and install third-party dependencies function ThirdPartyDeps() local repos = { { name = "Saike Tools", url = 'https://raw.githubusercontent.com/JoepVanlier/JSFX/master/index.xml' }, { name = "Suzuki Scripts", url = "https://github.com/Suzuki-Re/Suzuki-Scripts/raw/master/index.xml" }, } for i = 1, #repos do local retinfo = r.ReaPack_GetRepositoryInfo(repos[i].name) if not retinfo then r.ReaPack_AddSetRepository(repos[i].name, repos[i].url, true, 0) end end r.ReaPack_ProcessQueue(true) end -- Create ImGui context ctx = r.ImGui_CreateContext('ParaNormalFX Router') r.ImGui_SetConfigVar(ctx, r.ImGui_ConfigVar_WindowsMoveFromTitleBarOnly(), 1) ``` -------------------------------- ### Generate FX Browser Database Files Source: https://context7.com/gorankovac/reascripts/llms.txt Generates and saves database files for the FX Browser Parser, including a list of all installed plugins, their categories, and developers. This function should be called to initially build the cache. ```lua -- FX Browser Parser V7 -- File: FX/Sexan_FX_Browser_ParserV7.lua local r = reaper local script_path = debug.getinfo(1, "S").source:match [[^@?(.*[\/])[^\/]-$]] local FX_FILE = script_path .. "/FX_LIST.txt" local FX_CAT_FILE = script_path .. "/FX_CAT_FILE.txt" local FX_DEV_LIST_FILE = script_path .. "/FX_DEV_LIST_FILE.txt" -- Plugin tables local PLUGIN_LIST = {} local CAT = {} local DEVELOPER_LIST = { " (Waves)" } -- Generate FX database files function MakeFXFiles() GetFXTbl() -- Scans all plugins -- Serialize and save plugin list local serialized_fx = TableToString(PLUGIN_LIST) WriteToFile(FX_FILE, serialized_fx) -- Serialize and save categories local serialized_cat = TableToString(CAT) WriteToFile(FX_CAT_FILE, serialized_cat) -- Serialize and save developer list local serialized_dev_list = TableToString(DEVELOPER_LIST) WriteToFile(FX_DEV_LIST_FILE, serialized_dev_list) return PLUGIN_LIST, CAT, DEVELOPER_LIST end -- Read cached FX database function ReadFXFile() local fx_file = io.open(FX_FILE, "r") if fx_file then local fx_string = fx_file:read("*all") fx_file:close() PLUGIN_LIST = StringToTable(fx_string) end local cat_file = io.open(FX_CAT_FILE, "r") if cat_file then local cat_string = cat_file:read("*all") cat_file:close() CAT = StringToTable(cat_string) end return PLUGIN_LIST, CAT, DEVELOPER_LIST end -- Table serialization for persistence function TableToString(table) return SerializeToFile(table) end function StringToTable(str) local f, err = load("return " .. str) return f ~= nil and f() or nil end ``` -------------------------------- ### Initialize ReaSpaghetti and Load Modules Source: https://context7.com/gorankovac/reascripts/llms.txt Sets up the ImGui context and loads necessary modules for ReaSpaghetti. Requires the ReaImGui extension. Optionally supports Ultraschall API. ```lua -- ReaSpaghetti main initialization -- File: ReaSpaghetti/Sexan_ReaSpaghetti.lua local r = reaper -- Load ImGui API (requires ReaImGui extension) dofile(r.GetResourcePath() .. '/Scripts/ReaTeam Extensions/API/imgui.lua')('0.8.7') -- Create ImGui context ctx = r.ImGui_CreateContext('My script') -- Load required modules require("Modules/Defaults") require("Modules/APIParser") require("Modules/UI") require("Modules/Utils") require("Modules/Canvas") require("Modules/NodeDraw") require("Modules/Flow") require("Modules/CustomFunctions") require("Modules/ExportToAction") require("Modules/Library") require("Modules/Undo") -- Setup fonts for the interface FONT = r.ImGui_CreateFont('sans-serif', FONT_SIZE, r.ImGui_FontFlags_Bold()) FONT_CODE = r.ImGui_CreateFont('monospace', FONT_SIZE, r.ImGui_FontFlags_Bold()) r.ImGui_Attach(ctx, FONT) r.ImGui_Attach(ctx, FONT_CODE) -- Optional Ultraschall API support if r.file_exists(r.GetResourcePath() .. "/UserPlugins/ultraschall_api.lua") then dofile(r.GetResourcePath() .. "/UserPlugins/ultraschall_api.lua") ULTRA_API = true end -- Main rendering loop local function loop() r.ImGui_SetNextWindowSizeConstraints(ctx, 1100, 500, FLT_MAX, FLT_MAX) local visible, open = r.ImGui_Begin(ctx, 'ReaSpaghetti', true, WND_FLAGS) if visible then -- Render sidebar with node list Sidebar() -- Render canvas with nodes CanvasLoop() r.ImGui_End(ctx) end if open then r.defer(loop) end end loop() ``` -------------------------------- ### Initialize Pie3000 Radial Menu System Source: https://context7.com/gorankovac/reascripts/llms.txt Initializes the Pie3000 system, detects the mouse context, and loads menu configurations. Requires ImGui, JS_API, and SWS dependencies. ```lua -- Pie3000 initialization and context detection -- File: Pie3000/Sexan_Pie3000.lua local r = reaper local script_path = debug.getinfo(1, 'S').source:match [[^@?(.*[\]/)[^\/]-$]] package.path = script_path .. "?.lua;" .. package.path require('PieUtils') if CheckDeps() then return end -- Check for ImGui, JS_API, SWS ctx = r.ImGui_CreateContext('Pie 3000', r.ImGui_ConfigFlags_NoSavedSettings()) require('Common') -- Get monitor bounds for menu positioning local function GetMonitorFromPoint() local x, y = r.GetMousePosition() LEFT, TOP, RIGHT, BOT = r.my_getViewport(x, y, x, y, x, y, x, y, true) LEFT, TOP = LEFT + 10, TOP + 10 RIGHT, BOT = RIGHT - 10, BOT - 10 end -- Detect current mouse context for contextual menus local function GetMouseContext() local x, y = r.GetMousePosition() local track, info = r.GetThingFromPoint(x, y) local item, take = r.GetItemFromPoint(x, y, true) local cur_hwnd = r.JS_Window_FromPoint(x, y) local class_name = r.JS_Window_GetClassName(cur_hwnd) -- Determine context type if info:match("envelope") then return "envelope", track elseif info:match("^tcp") then return "tcp", track elseif info:match("^mcp") then return "mcp", track elseif item then return "item", item end return "arrange", nil end -- Initialize menu system local function Init() SCRIPT_START_TIME = r.time_precise() START_X, START_Y = r.ImGui_PointConvertNative(ctx, r.GetMousePosition()) GetMonitorFromPoint() CENTER = { x = START_X, y = START_Y } -- Load pie menu configurations PIES = ReadFromFile(pie_file) MIDI_PIES = ReadFromFile(midi_cc_file) -- Intercept the triggering key local key_state = r.JS_VKeys_GetState(SCRIPT_START_TIME - 1) for i = 1, 255 do if key_state:byte(i) ~= 0 then r.JS_VKeys_Intercept(i, 1) KEY = i break end end end ``` -------------------------------- ### Configure Pie Menu Actions in REAPER Source: https://context7.com/gorankovac/reascripts/llms.txt Provides a GUI for setting up REAPER actions within the Pie3000 radial menu system. Loads existing configurations or creates defaults. ```lua -- Pie menu configuration interface -- File: Pie3000/Sexan_Pie3000_Setup.lua (referenced from PieMenu/PieSetup.lua) local ctx = reaper.ImGui_CreateContext('My script') local fn = script_path .. "pie_menus.txt" -- Load existing pie configurations or create defaults local pie_txt = Read_from_file(fn) local PIES = StringToTable(pie_txt) or { ["arrange"] = {}, ["tcp"] = {}, ["mcp"] = {}, ["envelope"] = {}, ["item"] = {} } -- Iterate through all available actions in a section local function iterate_actions(sectionID) local i = 0 return function() local retval, name = reaper.CF_EnumerateActions(sectionID, i, '') if retval > 0 then i = i + 1 return retval, name end end end -- Get all main section actions local function Get_all_actions() local actions = {} for id, name in iterate_actions(0) do table.insert(actions, { id = id, name = name }) end table.sort(actions, function(a, b) return a.name < b.name end) return actions end -- Filter actions by search text local function Filter_actions(actions, filter_text) local t = {} for i = 1, #actions do local name = actions[i].name:lower() local found = true for word in filter_text:gmatch("%S+") do if not name:find(word:lower(), 1, true) then found = false break end end if found then table.insert(t, actions[i]) end end return t end ``` -------------------------------- ### Check ReaScript Dependencies Source: https://context7.com/gorankovac/reascripts/llms.txt Verifies if required ReaScript API extensions like Dear ImGui, js_ReaScriptAPI, and SWS/S&M are available. Displays a message box and opens ReaPack if dependencies are missing. ```lua -- Check for required dependencies function CheckDeps() local deps = {} if not reaper.ImGui_GetVersion then deps[#deps + 1] = '"Dear Imgui"' end if not reaper.JS_VKeys_Intercept then deps[#deps + 1] = '"js_ReaScriptAPI"' end if not reaper.SNM_SetIntConfigVar then deps[#deps + 1] = '"SWS/S&M"' end if #deps ~= 0 then reaper.ShowMessageBox( "Need Additional Packages.\nPlease Install it in next window", "MISSING DEPENDENCIES", 0) reaper.ReaPack_BrowsePackages(table.concat(deps, " OR ")) return true end end ``` -------------------------------- ### Open URL in Default Browser Source: https://context7.com/gorankovac/reascripts/llms.txt Opens a given URL in the system's default web browser. This function is cross-platform, supporting macOS, Windows, and Linux. ```lua -- Open URL in default browser (cross-platform) function Open_url(url) local OS = reaper.GetOS() if OS == "OSX64" or OS == "OSX32" or OS == 'macOS-arm64' then os.execute('open "' .. url .. '"') elseif OS == "Win64" or OS == "Win32" then os.execute('start "" "' .. url .. '"') else os.execute('xdg-open "' .. url .. '"') -- Linux end end ``` -------------------------------- ### Initialize ReaSpaghetti Canvas State Source: https://context7.com/gorankovac/reascripts/llms.txt Defines the initial state for the canvas, including view position, dimensions, offsets, and zoom level. This function should be called to create a new canvas object. ```lua -- Canvas initialization and control -- File: ReaSpaghetti/Modules/Canvas.lua function InitCanvas() local CANVAS = { view_x = 0, -- Canvas view X position view_y = 0, -- Canvas view Y position w = 0, -- Canvas width h = 0, -- Canvas height off_x = 100, -- X offset (pan) off_y = 200, -- Y offset (pan) scale = 1, -- Zoom level rx = 0, -- Content region X ry = 0 -- Content region Y } return CANVAS end ``` -------------------------------- ### Virtual Track Options Configuration Source: https://context7.com/gorankovac/reascripts/llms.txt This Lua code defines and manages options for Virtual Track, including tooltips, lane colors, and razor edit behavior. Options are loaded from and saved to REAPER's extension state. ```lua -- Options configuration and persistence -- File: VirtualTrack/Modules/VTCommon.lua OPTIONS = { ["TOOLTIPS"] = true, -- Show tooltips on hover ["LANE_COLORS"] = true, -- Unique color for each lane ["RAZOR_FOLLOW_SWAP"] = false, -- Razor follows version swap in lane mode } -- Load saved options from extension state if reaper.HasExtState("VirtualTrack", "options") then local state = reaper.GetExtState("VirtualTrack", "options") OPTIONS["LANE_COLORS"] = state:match("LANE_COLORS (%S+)") == "true" OPTIONS["TOOLTIPS"] = state:match("TOOLTIPS (%S+)") == "true" OPTIONS["RAZOR_FOLLOW_SWAP"] = state:match("RAZOR_FOLLOW_SWAP (%S+)") == "true" end -- Save options to extension state local function save_options() local store_string = "" for k, v in pairs(OPTIONS) do store_string = store_string .. tostring(k) .. " " .. tostring(v) .. " " end reaper.SetExtState("VirtualTrack", "options", store_string, true) end ``` -------------------------------- ### Read and Deserialize File Source: https://context7.com/gorankovac/reascripts/llms.txt Reads the entire content of a file and deserializes it into a Lua table using StringToTable. Returns nil if the file cannot be opened or is empty. ```lua -- Read and deserialize file contents function ReadFromFile(fn) local file = io.open(fn, "r") if not file then return end local content = file:read("a") if content == "" then return end return StringToTable(content) end ``` -------------------------------- ### Generate VSCode Lua Type Definitions for REAPER API Source: https://context7.com/gorankovac/reascripts/llms.txt Parses REAPER's API documentation to generate Lua type definitions for VSCode intellisense. Includes pre-defined Lua functions and GFX library type definitions. ```lua -- REAPER VSCode Definitions Generator -- File: ApiParser/ReaperDefinitionsGenerator.lua local API_PATH = "api_file.txt" -- Pre-defined Lua-specific function definitions local lua_func_str = [[ ---Adds code to be called back by REAPER for persistent scripts. ---@param function function ---@return boolean retval function reaper.defer(function) end ---Sets action options for the script. ---* flag&1: script will auto-terminate if re-launched ---* flag&2: if (flag&1) is set, script will re-launch after auto-terminating ---* flag&4: set script toggle state on ---* flag&8: set script toggle state off ---@param flag integer function reaper.set_action_options(flag) end ---Read value from shared memory attached by gmem_attach(). ---@param index integer ---@return number retval function reaper.gmem_read(index) end ---Write value to shared memory attached by gmem_attach(). ---@param index integer ---@param value number function reaper.gmem_write(index, value) end ]] -- GFX library type definitions local gfx_start_str = [[ ---@class gfx ---@field r number red component (0..1) ---@field g number green component (0..1) ---@field b number blue component (0..1) ---@field a number alpha for drawing (1=normal) ---@field w number width of UI framebuffer ---@field h number height of UI framebuffer ---@field x number current graphics position X ---@field y number current graphics position Y ---@field mouse_x number mouse X relative to graphics window ---@field mouse_y number mouse Y relative to graphics window ---@field mouse_cap number bitfield of mouse/keyboard modifiers gfx = {} ]] -- Function return type mappings for gfx functions local gfx_ret = { arc = { { type = "number", name = "retval" } }, blit = { { type = "number", name = "source" } }, blurto = { { type = "number", name = "retval" } }, } ``` -------------------------------- ### Debug Breakpoint with Message Source: https://context7.com/gorankovac/reascripts/llms.txt Sets a debug breakpoint that displays a message and a traceback in the REAPER console. Requires user confirmation to continue execution. ```lua -- Error handling and debugging utilities -- File: VirtualTrack/Modules/Utils.lua -- Debug breakpoint with message function Break(msg) local line = "Breakpoint at line " .. debug.getinfo(2).currentline local ln = "\n" .. string.rep("=", #line) .. "\n" local trace = debug.traceback(ln .. line) trace = trace:gsub("(stack traceback:\n).* ", "%1") reaper.ShowConsoleMsg(trace .. ln .. "\n") reaper.MB(tostring(msg) .. "\n\nContinue?", line, 0) end ``` -------------------------------- ### Smart Split with Automatic Crossfade Direction Source: https://context7.com/gorankovac/reascripts/llms.txt Intelligently splits selected media items and automatically creates crossfades. Determines crossfade direction based on mouse position relative to the edit cursor. ```lua -- Smart Split with automatic crossfade direction -- File: Items/Sexan_SmartSplit items crossfade left or right.lua local edit_cursor_pos = reaper.GetCursorPosition() local _, _, mouse_pos = reaper.BR_TrackAtMouseCursor() -- Determine crossfade direction based on mouse position local function cross_fade_pos() if edit_cursor_pos > mouse_pos then -- Mouse is left of edit cursor - crossfade left reaper.Main_OnCommand( reaper.NamedCommandLookup("_SWS_AWSPLITXFADELEFT"), 0) else -- Mouse is right of edit cursor - crossfade right reaper.Main_OnCommand(40759, 0) end end -- Smart split considering time selection function SmartSplit() local item = reaper.GetSelectedMediaItem(0, 0) local item_start = reaper.GetMediaItemInfo_Value(item, "D_POSITION") local item_len = reaper.GetMediaItemInfo_Value(item, "D_LENGTH") local item_end = item_start + item_len local Tstart, Tend = reaper.GetSet_LoopTimeRange(0, 0, 0, 0, 0) -- Check various time selection scenarios if Tstart == Tend then -- No time selection - use smart crossfade cross_fade_pos() elseif Tstart >= item_start and Tend <= item_end then -- Item spans time selection - split at time selection reaper.Main_OnCommand(40061, 0) else cross_fade_pos() end end local function Main() if reaper.CountSelectedMediaItems(0) > 0 then SmartSplit() end end Main() ``` -------------------------------- ### Save Data to File Source: https://context7.com/gorankovac/reascripts/llms.txt Writes string data to a specified file. Ensures the file is opened in write mode and closed after writing. ```lua -- Save data to file function SaveToFile(data, fn) local file = io.open(fn, "w") if file then file:write(data) file:close() end end ``` -------------------------------- ### Propagate Folder Track Arming Source: https://context7.com/gorankovac/reascripts/llms.txt Automatically arms/disarms child tracks when a parent folder track's record arm state changes. Requires Reaper and Lua environment. ```lua -- Folder track record/monitor arming propagation -- File: Track/Sexan_Folder record monitor arming childs.lua local last_proj_change_count = reaper.GetProjectStateChangeCount(0) -- Get folder depth at a track index function get_track_folder_depth(track_index) local folder_depth = 0 for i = 0, track_index do local track = reaper.GetTrack(0, i) folder_depth = folder_depth + reaper.GetMediaTrackInfo_Value(track, "I_FOLDERDEPTH") end return folder_depth end -- Handle record arm changes on folder tracks function on_rec_arm_change(track_pointer, track_index) local parent_folder_depth = get_track_folder_depth(track_index) local total_folder_depth = parent_folder_depth -- Get parent track states local parent_rec_arm = reaper.GetMediaTrackInfo_Value( track_pointer, "I_RECARM") local parent_mon_arm = reaper.GetMediaTrackInfo_Value(track_pointer, "I_RECMON") -- Apply to all child tracks for i = track_index + 1, reaper.CountTracks(0) do local child_track = reaper.GetTrack(0, i - 1) -- Set child track arm state to match parent reaper.SetMediaTrackInfo_Value( child_track, "I_RECARM", parent_rec_arm) reaper.SetMediaTrackInfo_Value( child_track, "I_RECMON", parent_mon_arm) -- Check if we've exited the folder total_folder_depth = total_folder_depth + reaper.GetMediaTrackInfo_Value(child_track, "I_FOLDERDEPTH") if total_folder_depth <= parent_folder_depth then break end end reaper.UpdateArrange() reaper.TrackList_AdjustWindows(false) end ``` -------------------------------- ### Element Class for Version Management Source: https://context7.com/gorankovac/reascripts/llms.txt The Element class in VTCommon.lua manages track and take version data, storing state information for versioning, comping, lane mode, and FX versions. It initializes with REAPER objects, version info, and optional FX data. ```lua -- Element class for version management -- File: VirtualTrack/Modules/VTCommon.lua local Element = {} function Element:new(rprobj, info, fx_data) local elm = {} elm.rprobj = rprobj -- REAPER object (MediaTrack* or MediaItem_Take*) elm.info = info -- Version info table elm.fx = fx_data or nil -- FX chain data elm.idx = 1 -- Current version index elm.comp_idx = reaper.ValidatePtr(rprobj, "MediaTrack*") and 0 or nil elm.lane_mode = reaper.ValidatePtr(rprobj, "MediaTrack*") and 0 or nil elm.group = reaper.ValidatePtr(rprobj, "MediaTrack*") and 0 or nil elm.fx_idx = reaper.ValidatePtr(rprobj, "MediaTrack*") and 1 or nil elm.def_icon = nil setmetatable(elm, self) self.__index = self return elm end -- Example: Create a new element for a track local track = reaper.GetSelectedTrack(0, 0) local version_info = { name = "Version 1", data = {} } local track_element = Element:new(track, version_info) ``` -------------------------------- ### Console Message Helper Source: https://context7.com/gorankovac/reascripts/llms.txt A simple helper function to display messages in the REAPER console, automatically appending a newline character. ```lua -- Console message helper function MSG(m) reaper.ShowConsoleMsg(tostring(m) .. "\n") end ``` -------------------------------- ### Deep Copy Table Source: https://context7.com/gorankovac/reascripts/llms.txt Creates a deep copy of a Lua table, including nested tables and metatables. Handles different data types recursively. ```lua -- Deep copy a table function Deepcopy(orig) local orig_type = type(orig) local copy if orig_type == 'table' then copy = {} for orig_key, orig_value in next, orig, nil do copy[Deepcopy(orig_key)] = Deepcopy(orig_value) end setmetatable(copy, Deepcopy(getmetatable(orig))) else copy = orig end return copy end ``` -------------------------------- ### Deserialize String to Lua Table Source: https://context7.com/gorankovac/reascripts/llms.txt Converts a string representation of a Lua table into an actual Lua table. Returns nil if the string is not valid Lua code. ```lua -- Deserialize string to Lua table function StringToTable(str) local f, err = load("return " .. str) return f ~= nil and f() or nil end ``` -------------------------------- ### Crash Handler with Error Reporting Source: https://context7.com/gorankovac/reascripts/llms.txt A crash handler that captures error messages and provides a detailed report to the console if the user chooses. It identifies the script name and REAPER version. ```lua -- Crash handler with detailed error reporting local crash = function(errObject) reaper.JS_VKeys_Intercept(-1, -1) local trimPath = "[\\/]([^\\/]-:%d+:.+)$" local err = errObject and string.match(errObject, trimPath) or "Couldn't get error message." local trace = debug.traceback() local name = ({reaper.get_action_context()})[2]:match("([^/\\_]+)$") local ret = reaper.ShowMessageBox( name .. " has crashed!\n\n" .. "Would you like a crash report printed to console?", "Oops", 4) if ret == 6 then reaper.ShowConsoleMsg( "Error: " .. err .. "\n\n" .. "Reaper: " .. reaper.GetAppVersion() .. "\n" .. "Platform: " .. reaper.GetOS()) end end function GetCrash() return crash end ``` -------------------------------- ### Implement Canvas Edge Scrolling Source: https://context7.com/gorankovac/reascripts/llms.txt Handles automatic canvas scrolling when the mouse is dragged near the canvas borders. This function should be called within the main loop when mouse dragging is detected. ```lua -- Edge scrolling when dragging near canvas borders function CanvasEdgeScrolling() if r.ImGui_IsMouseDragging(ctx, 0) and r.ImGui_IsWindowFocused(ctx) then EDGE_SCROLLING = { x = 0, y = 0 } if CANVAS.zone_L then CANVAS.off_x = CANVAS.off_x + EDGE_SCROLLING_SPEED end if CANVAS.zone_R then CANVAS.off_x = CANVAS.off_x - EDGE_SCROLLING_SPEED end end end ``` -------------------------------- ### Update Canvas Zoom Level Source: https://context7.com/gorankovac/reascripts/llms.txt Manages canvas zoom functionality using the mouse wheel. Zooms towards the mouse cursor position and enforces minimum and maximum zoom levels. ```lua -- Zoom control with mouse wheel local ZOOM_MIN, ZOOM_MAX, ZOOM_SPEED = 0.15, 1, 1 / 8 function UpdateZoom() if not r.ImGui_IsWindowHovered(ctx) then return end local new_scale = CANVAS.scale + (r.ImGui_GetMouseWheel(ctx) * ZOOM_SPEED) new_scale = math.max(ZOOM_MIN, math.min(ZOOM_MAX, new_scale)) if new_scale == CANVAS.scale then return end -- Zoom towards mouse cursor local scale_diff = (new_scale / CANVAS.scale) local mouse_x = MX - CANVAS.view_x - CANVAS.off_x local mouse_y = MY - CANVAS.view_y - CANVAS.off_y CANVAS.off_x = CANVAS.off_x + mouse_x - (mouse_x * scale_diff) CANVAS.off_y = CANVAS.off_y + mouse_y - (mouse_y * scale_diff) CANVAS.scale = new_scale end ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.