diff --git a/README.html b/README.html
new file mode 100644
index 0000000..fdf1458
--- /dev/null
+++ b/README.html
@@ -0,0 +1,1157 @@
+
MonkeyBars Reaper Scripts
+The URL to import in ReaPack is https://github.com/MonkeyBars3k/ReaScripts/raw/master/index.xml.
+Superglue
+Background
+There are two main ways to consolidate selected items on a track natively in Reaper: Glue and Groups. Both have disadvantages.
+Glue is permanent: once you glue items together, you cannot make edits later without cutting again. This can be problematic as you may wish make any number of changes to enclosed items (such as make the sound of a kick drum’s tail longer, etc.). You cannot do this using Glue, a “destructive” edit.
+The other option is to Group items. This works well if you simply want to move items around or select multiple items by clicking one item; however, you cannot use many other benefits of a single Reaper item, such as quickly looping, take envelopes etc. Grouping can also become confusing because Groups are highlighted in green around the items, but not around the boundary of the group itself. Groups can be unwieldy to work with in many musical contexts, such as a four-bar repetition, and they tend to create visual clutter.
+Superglue aims to address the shortcomings of both Glue and Groups, restore the convenient functionality already present in items (looping, timestretching, and much more) by placing selected items in a new container item called a Superitem – and provide users the convenience of audio item pooling.
+How to use
+To Superglue items, simply select items and trigger one of the MB_Superglue Glue or Smart Action scripts.
+To change the contents of your Superitem, the Edit script “opens” the created Superitem, restoring the contained items once again. To Reglue, just use one of the Glue or Smart Action scripts again. The Unglue scripts restore the contained items to their state from before that pool’s last Superglue (i.e., irreversibly restored the contained items in the Superitem).
+Smart Action scripts intelligently determine which action is required based on your item selection!
+Features
+
+- Provides the missing nondestructive/reversible Glue feature in Reaper!
+- A.k.a.: Glue Groups, Item Containers, Container Items, Pooled Item Boxes, Pooled Audio Items
+- Provides the missing pooled audio items feature in Reaper!
+- Superitem copies are pooled by default. Editing and regluing one Superitem updates all instances.
+- Run the script to Remove Superitem from current Pool to place a Superitem on its own new Pool.
+- Disable Superitem pooling by enabling the option to Remove Superitem siblings from Pool on Glue. Careful: this removes formerly copied Superitems from their pools. If you want a mix of pooled and unpooled Superitems, it’s recommended to run the script to Remove Superitem from Pool manually as needed.
+- Supports nesting Superitems inside other Superitems! When you update the nested Superitem, Superglue checks the parent item and updates that Superitem as well. There is no limit in the code as to how many times you can nest Superitems – tested with 20 levels of nesting.
+- Superglue has its own script options that can be selected by the user. Just run the script to open the options window and try them out. Scripts are supplied to toggle Boolean (on/off) options.
+- You can toggle expansion to time selection in the options window.
+
+Tips
+
+- Using just the pooled audio item feature: Feel free to Superglue a single audio item and make copies of that! Since every Superitem you copy is a pooled audio item, all you need to ensure all the copies stay updated is to Edit any one of the pooled Superitems and Reglue.
+- Using just the container feature: The most basic application of Superglue is probably just treating your Superitem as a container item that can be edited easily later, i.e. a more convenient way to group items.
+- Check out all the scripts that get installed when you sync the ReaPack repo. There are some very useful utilities.
+- Make sure to examine the options window which enables numerous configurations for various use cases.
+- If you want to store items that extend beyond the Superitem you wish to create, just disable the option to Allow sizing region to reduce Superitem size.
+- While Superglue does add a default Pool indicator prefix to Superitem take names, you may end up changing the name. In this and other cases, it’s useful to open up the Superglue item info window to see its Parent Pool ID and other relevant Superglue data.
+
+Requirements
+
+- Requires Reaper v6.43 or newer
+- Requires SWS Plugin Extension and js_ReaScript_API Plugin Extension
+
+Warnings
+Audio sources
+
+- Be very careful if you want to Clean current project directory after Supergluing – you could lose contained items’ audio, since at that point those “items” aren’t included in the project proper – they only exist as data (state chunks).
+- Stay aware of the state of your Superitems whenever editing audio externally. If you’re destructively editing audio in a contained item, or for example editing a subproject which is present as a contained item in a Superitem, such items’ direct parent must be in Edit mode (“open”) during your external audio source edits, or their ancestors (parent, grandparent, etc. Superitems) won’t be updated.
+
+MIDI
+
+- Currently only MIDI on virtual instrument tracks is supported.
+- To create MIDI Superitems, the script uses “Apply track FX as new take” on each item to get an audio take. When you Edit, the audio take is removed and just the original MIDI take is made active.
+
+Editing Superitems
+
+- When you Edit a Superitem, a special white region is automatically created so you can alter the Superitem’s edge positions after Reglue. Superglue displays a warning message should you delete this “sizing region”. (This message can be disabled in the options, in which case when you delete the sizing region, the items will revert to their presuperglued state as if you had Unglued.) Be careful undoing sizing region deletion, as the defer loop (constantly checking for sizing region deletion by the user) often gets confused.
+- Be careful Editing a parent Superitem near project start. If a child Superitem would extend before project start, its source offset will adjust automatically so its audio is in the right place, but regluing could affect its sibling pooled Superitems.
+- Remember that restored items can extend beyond the size of your Superitem on Edit. Stay aware of content in tracks (such as items, track envelopes, etc.) nearby.
+- Reaper throws warnings that scripts are “running again” in various situations with Superglue (since it runs defer scripts), such as when you Edit more than one Superitem at the same time, and other cases. In Reaper’s dialog, just select that you want to allow the Superglue script in question to run (always, if you don’t like getting prompted). ReaScript devs can’t get around this message until this FR is implemented.
+
+Superitem configuration
+
+- Multiple takes on Superitems are not supported. If you try to Edit a Superitem with multiple takes, you’ll be prompted to explode them or cancel.
+- Set the item mix behavior on your items (and tracks) very carefully, as that affects how your items glue. Unfortunately, the ReaScript API does not allow setting this mode directly yet.
+- When using copies of Superitems, you can’t Superglue a copy of itself inside itself, as that would cause an infinite recursion and implode the universe in a Big Crunch type event. (This actually happened during dev a few times but I was safe inside my pocket microverse and just undid reality.)
+- Superglue uses item notes to set background images for easy recognition of Superitems and contained items. Careful: The background image will overwrite any item notes you already have on your glued items. Just disable this feature in the script options window or with the included script if you don’t like it for any reason.
+
+Potential project conflicts
+
+- Superglue uses item selection set slot 10 and SWS time selection set slot 5.
+
+Glossary
+
+- Ancestor: A Superitem in which another Superitem or other Superitems are nested – parents, grandparents, etc. are ancestors.
+- Child: A Superitem which is nested (superglued) inside another Superitem (its parent)
+- Contained items: Items whose data (“state chunks” in ReaScript parlance) are referenced in a Superitem’s data
+- Descendant: A Superitem nested one or more levels inside another Superitem – children, grandchildren, etc. are descendants.
+- Edit: Restore a Superitem into its “contained” items reversibly/nondestructively, maintaining the ability to Reglue them and retain Superitem properties and update its pool siblings
+- Instance: Any Superitem from a given Pool
+- Nest: Superglue a Superitem into or inside another Superitem
+- Parent: The Superitem in which another Superitem is directly nested
+- Pool: A group of siblings that update each other if Edited
+- Reglue: Run a Superglue Glue script on items restored from an instance (in Edit mode)
+- Restored items: Contained items which reappear after running an Edit or Unglue script on a Superitem
+- Sibling: Pooled copy of a Superitem – Edit any sibling, and all its sibling and ancestor Superitems get updated as well.
+- Smart Action: Superglue script that tries to guess the user’s intention from the item selection – sometimes you’ll be prompted for an action choice or warned that none can be determined automagically.
+- Superitem: The resulting “container item” after Supergluing – really it’s just a normal Reaper item, but Superglue stores all the data about the items that were glued into it, etc.
+- Unglue: Restore a Superitem into its contained items irreversibly/destructively, deleting any connection to their pool and any of the former Superitem’s properties
+
+History
+matthewjumpsoffbuildings created the powerful, excellent “Glue Groups” scripts: https://bitbucket.org/matthewjumpsoffbuildings/reaper-scripts/src/master/
+MonkeyBars continues the effort with some different nomenclature (in the interest of onboarding new users and making it easy to find in the Actions Window), bugfixes, and additional features.
+Planned improvements
+See enhancement Issues.
+Report a Bug
+Add a bug Issue here.
\ No newline at end of file
diff --git a/README.md b/README.md
index cccdac7..f1057ee 100644
--- a/README.md
+++ b/README.md
@@ -39,6 +39,7 @@ To change the contents of your Superitem, the **Edit** script "opens" the create
- **Using just the container feature:** The most basic application of Superglue is probably just treating your Superitem as a container item that can be edited easily later, i.e. a more convenient way to group items.
- Check out **all the scripts** that get installed when you sync the ReaPack repo. There are some very useful utilities.
- Make sure to examine the **options window** which enables numerous configurations for various use cases.
+- Contained Items can extend beyond your Superitem edges, enabling an **extradimensional pocket to hide items in your project** without having to hide a track or add muted items anywhere.
- While Superglue does add a default Pool indicator prefix to Superitem take names, you may end up changing the name. In this and other cases, it's useful to open up the **Superglue item info window** to see its Parent Pool ID and other relevant Superglue data.
### Requirements
@@ -53,7 +54,7 @@ To change the contents of your Superitem, the **Edit** script "opens" the create
- Currently only **MIDI on virtual instrument tracks** is supported.
- To create **MIDI Superitems**, the script uses "Apply track FX as new take" on each item to get an audio take. When you Edit, the audio take is removed and just the original MIDI take is made active.
#### Editing Superitems
-- When you Edit a Superitem, a **special white region** is automatically created so you can expand the size of the Superitem past its contained items once it is reglued. Superglue displays a warning message should you delete this "sizing region". (This message can be disabled in the options, in which case when you delete the sizing region, the items will revert to their presuperglued state as if you had Unglued.) **Be careful undoing** sizing region deletion, as the defer loop (constantly checking for sizing region deletion by the user) often gets confused.
+- When you Edit a Superitem, a **special white region** is automatically created so you can alter the Superitem's eventual edge positions after Reglue. Superglue displays a warning message should you delete this "sizing region". (This message can be disabled in the options, in which case when you delete the sizing region, the items will revert to their presuperglued state as if you had Unglued.) **Be careful undoing** sizing region deletion, as the defer loop (constantly checking for sizing region deletion by the user) often gets confused.
- Be careful Editing a parent Superitem **near project start**. If a child Superitem would extend before project start, its source offset will adjust automatically so its audio is in the right place, but regluing could affect its sibling pooled Superitems.
- Remember that **restored items can extend beyond the size of your Superitem** on Edit. Stay aware of content in tracks (such as items, track envelopes, etc.) nearby.
- Reaper throws warnings that scripts are "running again" in various situations with Superglue (since it runs defer scripts), such as when you **Edit more than one Superitem** at the same time, and other cases. In Reaper's dialog, just select that you want to allow the Superglue script in question to run (always, if you don't like getting prompted). ReaScript devs can't get around this message until [this FR](https://forum.cockos.com/showthread.php?t=202416) is implemented.
@@ -70,7 +71,7 @@ To change the contents of your Superitem, the **Edit** script "opens" the create
- **Child**: A Superitem which is nested (superglued) inside another Superitem (its parent)
- **Contained items**: Items whose data ("state chunks" in ReaScript parlance) are referenced in a Superitem's data
- **Descendant**: A Superitem nested one or more levels inside another Superitem – children, grandchildren, etc. are descendants.
-- **Edit**: Restore a Superitem into its "contained" items reversibly/nondestructively, maintaining the ability to reglue them and retain Superitem properties and update its pool siblings
+- **Edit**: Restore a Superitem into its "contained" items reversibly/nondestructively, maintaining the ability to Reglue them and retain Superitem properties and update its pool siblings
- **Instance**: Any Superitem from a given Pool
- **Nest**: Superglue a Superitem into or inside another Superitem
- **Parent**: The Superitem in which another Superitem is directly nested
diff --git a/Superglue/MB_Superglue - Cycle option, Maintain siblings' audio source position.lua b/Superglue/MB_Superglue - Cycle option, Maintain siblings' audio source position.lua
new file mode 100644
index 0000000..51d8622
--- /dev/null
+++ b/Superglue/MB_Superglue - Cycle option, Maintain siblings' audio source position.lua
@@ -0,0 +1,13 @@
+-- @description MB_Superglue - Maintain siblings' audio source position
+-- @author MonkeyBars
+-- @version 1.786
+-- @changelog Initial upload
+-- @provides [main] .
+-- @link Forum https://forum.cockos.com/showthread.php?t=136273
+-- @about Fork of matthewjumpsoffbuildings's Glue Groups scripts
+
+
+package.path = package.path .. ";" .. string.match(({reaper.get_action_context()})[2], "(.-)([^\\/]-%.?([^%.\\/]*))$") .. "?.lua"
+require("MB_Superglue-Utils")
+
+toggleOption("maintain_source_position_default")
\ No newline at end of file
diff --git a/Superglue/MB_Superglue-Utils.lua b/Superglue/MB_Superglue-Utils.lua
index d64a616..382df5c 100644
--- a/Superglue/MB_Superglue-Utils.lua
+++ b/Superglue/MB_Superglue-Utils.lua
@@ -1,7 +1,7 @@
-- @description MB_Superglue-Utils: Codebase for MB_Superglue scripts' functionality
-- @author MonkeyBars
--- @version 1.785
--- @changelog Issue 228 fix
+-- @version 1.786
+-- @changelog Sizing region & time selection can shrink final Superitem size (https://github.com/MonkeyBars3k/ReaScripts/issues/207); Restored item bg image not loading in (https://github.com/MonkeyBars3k/ReaScripts/issues/229)
-- @provides [nomain] .
-- serpent.lua
-- rtk.lua
@@ -21,14 +21,14 @@
-- General utility functions at bottom
-- for dev only
-require("sg-dev-functions")
+-- require("sg-dev-functions")
local serpent = require("serpent")
local rtk = require('rtk')
-local _script_path, _superitem_bg_img_path, _restored_item_bg_img_path, _peak_data_filename_extension, _scroll_action_id, _save_time_selection_slot_5_action_id, _restore_time_selection_slot_5_action_id, _crop_selected_items_to_time_selection_action_id, _script_brand_name, _glue_undo_block_string, _edit_undo_block_string, _unglue_undo_block_string, _depool_undo_block_string, _smart_action_undo_block_string, _color_undo_block_string, _reinstate_sizing_region_undo_block_string, _sizing_region_label, _sizing_region_color, _api_current_project, _api_command_flag, _api_include_all_undo_states, _api_marker_region_undo_states, _api_item_image_full_height, _api_time_value_decimal_resolution, _api_extstate_persist_enabled, _api_data_key, _api_project_region_guid_key_prefix, _api_item_mute_key, _api_item_position_key, _api_item_length_key, _api_item_notes_key, _api_item_color_key, _api_take_src_offset_key, _api_take_playrate, _api_take_name_key, _api_takenumber_key, _api_null_takes_val, _global_script_prefix, _global_script_item_name_prefix, _separator, _superitem_name_prefix, _pool_key_prefix, _all_pool_ids_with_active_sizing_regions_key, _sizing_region_defer_loop_suffix, _pool_contained_item_states_key_suffix, _pool_last_glue_contained_item_states_key_suffix, _pool_parent_position_key_suffix, _pool_parent_length_key_suffix, _instance_pool_id_key_suffix, _parent_pool_id_key_suffix, _descendant_pool_ids_key_suffix, _last_pool_id_key_suffix, _preglue_active_take_guid_key_suffix, _superglue_active_take_key_suffix, _glue_data_key_suffix, _edit_data_key_suffix, _superitem_params_suffix, _parent_pool_ids_data_key_suffix, _superitem_preglue_state_suffix, _item_offset_to_superitem_position_key_suffix, _postglue_action_step, _preedit_action_step, _superitem_name_default_prefix, _nested_item_default_name, _double_quotation_mark, _msg_type_ok, _msg_type_ok_cancel, _msg_type_yes_no, _msg_response_ok, _msg_response_yes, _msg_response_no, _msg_change_selected_items, _data_storage_track, _active_glue_pool_id, _position_start_of_project, _src_offset_reset_value, _sizing_region_1st_display_num, _sizing_region_defer_timing, _superitem_instance_offset_delta_since_last_glue, _restored_items_project_start_position_delta, _last_glue_stored_item_states, _preglue_restored_item_states, _ancestor_pools_params, _position_changed_since_last_glue, _position_propagate_response, _active_instance_length_has_changed, _pool_parent_last_glue_length, _length_propagate_response, _maintain_source_position_response, _playrate_affects_propagation_response, _user_wants_to_depool_all_siblings, _global_options_section, _global_option_toggle_expand_to_time_selection_key, _global_option_toggle_auto_increase_channel_count_key, _global_option_toggle_item_images_key, _global_option_toggle_new_superglue_random_color_key, _global_option_toggle_sizing_region_deletion_msg_key, _global_option_toggle_depool_all_siblings_on_reglue_key, _global_option_toggle_depool_all_siblings_on_reglue_warning_key, _global_option_maintain_source_position_default_key, _global_option_propagate_position_default_key, _global_option_propagate_length_default_key, _global_option_playrate_affects_propagation_default_key, _all_global_options_params
+local _script_path, _superitem_bg_img_path, _restored_item_bg_img_path, _peak_data_filename_extension, _scroll_action_id, _save_time_selection_slot_5_action_id, _restore_time_selection_slot_5_action_id, _crop_selected_items_to_time_selection_action_id, _script_brand_name, _glue_undo_block_string, _edit_undo_block_string, _unglue_undo_block_string, _depool_undo_block_string, _smart_action_undo_block_string, _color_undo_block_string, _reinstate_sizing_region_undo_block_string, _sizing_region_label, _sizing_region_color, _api_current_project, _api_command_flag, _api_include_all_undo_states, _api_marker_region_undo_states, _api_item_image_full_height, _api_time_value_decimal_resolution, _api_extstate_persist_enabled, _api_data_key, _api_project_region_guid_key_prefix, _api_item_mute_key, _api_item_position_key, _api_item_length_key, _api_item_notes_key, _api_item_color_key, _api_take_src_offset_key, _api_take_playrate, _api_take_name_key, _api_takenumber_key, _api_null_takes_val, _global_script_prefix, _global_script_item_name_prefix, _separator, _superitem_name_prefix, _pool_key_prefix, _all_pool_ids_with_active_sizing_regions_key, _sizing_region_defer_loop_suffix, _pool_contained_item_states_key_suffix, _pool_last_glue_contained_item_states_key_suffix, _pool_parent_position_key_suffix, _pool_parent_length_key_suffix, _instance_pool_id_key_suffix, _parent_pool_id_key_suffix, _descendant_pool_ids_key_suffix, _last_pool_id_key_suffix, _preglue_active_take_guid_key_suffix, _superglue_active_take_key_suffix, _glue_data_key_suffix, _edit_data_key_suffix, _superitem_params_suffix, _parent_pool_ids_data_key_suffix, _superitem_preglue_state_suffix, _item_offset_to_superitem_position_key_suffix, _postglue_action_step, _preedit_action_step, _superitem_name_default_prefix, _nested_item_default_name, _double_quotation_mark, _msg_type_ok, _msg_type_ok_cancel, _msg_type_yes_no, _msg_response_ok, _msg_response_yes, _msg_response_no, _msg_change_selected_items, _data_storage_track, _active_glue_pool_id, _position_start_of_project, _src_offset_default_value, _take_playrate_default_value, _sizing_region_1st_display_num, _sizing_region_defer_timing, _superitem_instance_offset_delta_since_last_glue, _restored_items_project_start_position_delta, _last_glue_stored_item_states, _preglue_restored_item_states, _contained_items_outside, _ancestor_pools_params, _position_changed_since_last_glue, _position_propagate_response, _active_instance_length_has_changed, _pool_parent_last_glue_length, _length_propagate_response, _maintain_source_position_response, _playrate_affects_propagation_response, _user_wants_to_depool_all_siblings, _global_options_section, _global_option_toggle_expand_to_time_selection_key, _global_option_toggle_auto_increase_channel_count_key, _global_option_toggle_item_images_key, _global_option_toggle_new_superglue_random_color_key, _global_option_toggle_sizing_region_deletion_msg_key, _global_option_toggle_depool_all_siblings_on_reglue_key, _global_option_toggle_depool_all_siblings_on_reglue_warning_key, _global_option_maintain_source_position_default_key, _global_option_propagate_position_default_key, _global_option_propagate_length_default_key, _global_option_playrate_affects_propagation_default_key, _all_global_options_params
_script_path = string.match(({reaper.get_action_context()})[2], "(.-)([^\\/]-%.?([^%.\\/]*))$")
_superitem_bg_img_path = _script_path .. "sg-bg-superitem.png"
@@ -46,7 +46,7 @@ _depool_undo_block_string = "MB_Superglue-DePool"
_smart_action_undo_block_string = "MB_Superglue-Smart-Action"
_color_undo_block_string = "MB_Superglue-Color"
_reinstate_sizing_region_undo_block_string = "MB_Superglue-Reinstate-Sizing-Region"
-_sizing_region_label = "SG: DO NOT DELETE – Use to increase size – Pool #"
+_sizing_region_label = "SG: DO NOT DELETE – Use to set Superitem edges – Pool #"
_sizing_region_color = reaper.ColorToNative(255, 255, 255)|0x1000000
_api_current_project = 0
_api_command_flag = 0
@@ -106,13 +106,15 @@ _msg_change_selected_items = "Change the items selected and try again."
_data_storage_track = reaper.GetMasterTrack(_api_current_project)
_active_glue_pool_id = nil
_position_start_of_project = 0
-_src_offset_reset_value = 0
+_src_offset_default_value = 0
+_take_playrate_default_value = 1
_sizing_region_1st_display_num = 0
_sizing_region_defer_timing = 0.5
_superitem_instance_offset_delta_since_last_glue = 0
_restored_items_project_start_position_delta = 0
_last_glue_stored_item_states = nil
_preglue_restored_item_states = nil
+_contained_items_outside = nil
_ancestor_pools_params = {}
_position_changed_since_last_glue = false
_position_propagate_response = nil
@@ -583,7 +585,7 @@ end
function initAction(action)
local selected_item_count
- selected_item_count = doPreGlueChecks()
+ selected_item_count = doPreGlueChecks(action)
if selected_item_count == false then return false end
@@ -597,7 +599,7 @@ function initAction(action)
end
-function doPreGlueChecks()
+function doPreGlueChecks(action)
local selected_item_count
if renderPathIsValid() == false then return false end
@@ -608,6 +610,12 @@ function doPreGlueChecks()
if requiredLibsAreInstalled() == false then return false end
+ if action == "glue" then
+
+ if itemsAreOffscreen(selected_item_count, action) == true then return false end
+
+ end
+
return selected_item_count
end
@@ -671,6 +679,56 @@ function requiredLibsAreInstalled()
end
+function itemsAreOffscreen(item_count, action)
+ local i, this_selected_item_is_before_arrange_view, this_selected_item_is_after_arrange_view, offscreen_msg_text_start, offscreen_msg_text_end, offscreen_msg_text_item_type, offscreen_msg_text, items_offscreen_response
+
+ for i = 0, item_count-1 do
+ this_selected_item_is_before_arrange_view, this_selected_item_is_after_arrange_view, offscreen_msg_text_start, offscreen_msg_text_end = getOffscreenItemParams(i)
+
+ if this_selected_item_is_before_arrange_view or this_selected_item_is_after_arrange_view then
+
+ if action == "glue" then
+ offscreen_msg_text_item_type = "selected"
+ offscreen_msg_text = _script_brand_name .. ": " .. offscreen_msg_text_start .. offscreen_msg_text_item_type .. offscreen_msg_text_end
+ items_offscreen_response = reaper.ShowMessageBox("Select OK to continue with the items selected or Cancel to abort.", offscreen_msg_text, _msg_type_ok_cancel)
+
+ if items_offscreen_response == _msg_response_ok then
+ return false
+
+ else
+ return true
+ end
+
+ elseif action == "Edit" or action == "Unglue" then
+ offscreen_msg_text_item_type = "restored"
+ offscreen_msg_text = offscreen_msg_text_start .. offscreen_msg_text_item_type .. offscreen_msg_text_end
+
+ reaper.ShowMessageBox(offscreen_msg_text, _script_brand_name .. " Warning", _msg_type_ok)
+
+ break
+ end
+ end
+ end
+end
+
+
+function getOffscreenItemParams(i)
+ local this_selected_item, this_selected_item_position, this_selected_item_length, this_selected_item_end_point, arrange_start_time, arrange_end_time, this_selected_item_is_before_arrange_view, this_selected_item_is_after_arrange_view, offscreen_msg_text_start, offscreen_msg_text_end
+
+ this_selected_item = reaper.GetSelectedMediaItem(_api_current_project, i)
+ this_selected_item_position = reaper.GetMediaItemInfo_Value(this_selected_item, _api_item_position_key)
+ this_selected_item_length = reaper.GetMediaItemInfo_Value(this_selected_item, _api_item_length_key)
+ this_selected_item_end_point = this_selected_item_position + this_selected_item_length
+ arrange_start_time, arrange_end_time = reaper.GetSet_ArrangeView2(_api_current_project, false, 0, 0)
+ this_selected_item_is_before_arrange_view = this_selected_item_position < arrange_start_time
+ this_selected_item_is_after_arrange_view = this_selected_item_end_point > arrange_end_time
+ offscreen_msg_text_start = "One or more "
+ offscreen_msg_text_end = " items extend beyond the current visible Arrange window view."
+
+ return this_selected_item_is_before_arrange_view, this_selected_item_is_after_arrange_view, offscreen_msg_text_start, offscreen_msg_text_end
+end
+
+
function prepareAction(action)
reaper.Undo_BeginBlock()
reaper.PreventUIRefresh(1)
@@ -1046,7 +1104,7 @@ function handleGlue(selected_items, first_selected_item_track, pool_id, sizing_r
deselectAllItems()
pool_id, sizing_params, time_selection_was_set_by_code, this_is_reglue = setUpGlue(depool_superitem_params, this_is_parent_update, first_selected_item_track, pool_id, restored_items_position_adjustment, sizing_region_guid, selected_items)
- selected_item_states, selected_instances_pool_ids, selected_items_length = handlePreglueItems(selected_items, pool_id, sizing_params, first_selected_item_track, this_is_parent_update)
+ selected_item_states, selected_instances_pool_ids, selected_items_length = handlePreglueItems(selected_items, pool_id, sizing_params, this_is_parent_update)
superitem = glueSelectedItemsIntoSuperitem()
handlePostGlue(selected_items, pool_id, first_selected_item_name, superitem, selected_instances_pool_ids, sizing_params, selected_items_length, this_is_reglue, this_is_parent_update, time_selection_was_set_by_code)
@@ -1100,6 +1158,7 @@ function setUpGlue(depool_superitem_params, this_is_parent_update, first_selecte
if this_is_new_glue then
pool_id = handlePoolId()
+ sizing_params = calculateSizingTimeSelection(selected_items, sizing_params)
if this_is_depool then
pool_contained_item_states_key = _pool_key_prefix .. pool_id .. _pool_contained_item_states_key_suffix
@@ -1243,9 +1302,8 @@ function setUpUserSelectedInstanceReglue(sizing_region_guid, active_track, selec
sizing_region_defer_loop_is_active_key = _pool_key_prefix .. pool_id .. _sizing_region_defer_loop_suffix
if is_active_superitem_reglue then
- if obey_time_selection == "false" or (obey_time_selection == "true" and no_time_selection_exists) then
- sizing_params = calculateSizingTimeSelection(selected_items, sizing_params)
+ if obey_time_selection == "false" or (obey_time_selection == "true" and no_time_selection_exists) then
setResetGlueTimeSelection(sizing_params, "set")
time_selection_was_set_by_code = true
@@ -1402,19 +1460,28 @@ function calculateSizingTimeSelection(selected_items, sizing_params)
if earliest_selected_item_position then
earliest_selected_item_position = math.min(earliest_selected_item_position, this_selected_item_position)
+
else
earliest_selected_item_position = this_selected_item_position
end
-
+
if latest_selected_item_end_point then
latest_selected_item_end_point = math.max(latest_selected_item_end_point, this_selected_item_end_point)
+
else
latest_selected_item_end_point = this_selected_item_end_point
end
end
- sizing_params.position = math.min(sizing_params.position, earliest_selected_item_position)
- sizing_params.end_point = math.max(sizing_params.end_point, latest_selected_item_end_point)
+ if not sizing_params then
+ sizing_params = {
+ ["position"] = earliest_selected_item_position,
+ ["end_point"] = latest_selected_item_end_point
+ }
+
+ else
+ sizing_params.position = math.min(sizing_params.position, earliest_selected_item_position)
+ end
return sizing_params
end
@@ -1435,7 +1502,7 @@ function setUpDePool(depool_superitem_params)
end
-function handlePreglueItems(selected_items, pool_id, sizing_params, first_selected_item_track, this_is_parent_update)
+function handlePreglueItems(selected_items, pool_id, sizing_params, this_is_parent_update)
local selected_item_states, selected_instances_pool_ids, i, selected_items_position, last_selected_item_position, last_selected_item_length, selected_items_end_point, selected_items_length
setPreglueItemsData(selected_items, pool_id, sizing_params)
@@ -1445,10 +1512,13 @@ function handlePreglueItems(selected_items, pool_id, sizing_params, first_select
storeItemStates(pool_id, selected_item_states)
selectDeselectItems(selected_items, true)
- if this_is_parent_update then
+ sizing_params.position = round(sizing_params.position, _api_time_value_decimal_resolution)
+ sizing_params.end_point = round(sizing_params.end_point, _api_time_value_decimal_resolution)
+
+ if not this_is_parent_update then
for i = 1, #selected_items do
- cropItemToSizingParams(selected_items[i], sizing_params, first_selected_item_track)
+ cropItemToSizingParams(selected_items[i], sizing_params)
end
end
@@ -1604,41 +1674,112 @@ function selectDeselectItems(items, select_deselect)
end
-function cropItemToSizingParams(restored_item, sizing_item_params, active_track)
- local restored_item_params, restored_item_starts_before_parent, restored_item_ends_later_than_parent, restored_item_parent_pool_id, right_hand_split_item, restored_item_cropped_position_delta, restored_item_active_take, restored_vs_sizing_item_length_delta, restored_item_new_length, end_point_delta
+function cropItemToSizingParams(restored_item, sizing_params)
+ local restored_item_params, restored_item_ends_before_parent, restored_item_starts_before_parent, restored_item_ends_later_than_parent, restored_item_starts_after_parent, end_point_delta
- restored_item_params = getSetItemParams(restored_item)
+ restored_item_params, restored_item_ends_before_parent, restored_item_starts_before_parent, restored_item_ends_later_than_parent, restored_item_starts_after_parent = getItemCropParams(restored_item, sizing_params)
- restored_item_starts_before_parent = round(restored_item_params.position, _api_time_value_decimal_resolution) < round(sizing_item_params.position, _api_time_value_decimal_resolution)
- restored_item_ends_later_than_parent = round(restored_item_params.end_point, _api_time_value_decimal_resolution) > round(sizing_item_params.end_point, _api_time_value_decimal_resolution)
- restored_item_parent_pool_id = storeRetrieveItemData(restored_item, _parent_pool_id_key_suffix)
+ if restored_item_ends_before_parent or restored_item_starts_after_parent then
+ reaper.SetMediaItemSelected(restored_item, false)
+
+ if not _contained_items_outside then
+ _contained_items_outside = {}
+ end
- if restored_item_starts_before_parent then
- restored_item_cropped_position_delta = sizing_item_params.position - restored_item_params.position
- restored_item_active_take = reaper.GetTake(restored_item, restored_item_params.active_take_num)
+ table.insert(_contained_items_outside, restored_item)
- reaper.SetMediaItemPosition(restored_item, sizing_item_params.position, true)
- reaper.SetMediaItemTakeInfo_Value(restored_item_active_take, _api_take_src_offset_key, restored_item_cropped_position_delta)
+ else
+
+ if restored_item_starts_before_parent then
+ cropItemStartingBeforeParent(restored_item, restored_item_params, sizing_params)
+ end
+
+ if restored_item_ends_later_than_parent then
+ end_point_delta = restored_item_params.end_point - sizing_params.end_point
+ restored_item_new_length = restored_item_params.length - end_point_delta
- restored_item_params.length = reaper.GetMediaItemInfo_Value(restored_item, _api_item_length_key)
- restored_vs_sizing_item_length_delta = restored_item_params.length - sizing_item_params.length
-
- if restored_vs_sizing_item_length_delta > 0 then
- restored_item_new_length = restored_item_params.length - restored_vs_sizing_item_length_delta
-
reaper.SetMediaItemLength(restored_item, restored_item_new_length, false)
end
end
+end
+
- if restored_item_ends_later_than_parent then
- end_point_delta = restored_item_params.end_point - sizing_item_params.end_point
- restored_item_new_length = restored_item_params.length - end_point_delta
+function getItemCropParams(restored_item, sizing_params)
+ local restored_item_params, restored_item_ends_before_parent, restored_item_starts_before_parent, restored_item_ends_later_than_parent, restored_item_starts_after_parent
+
+ restored_item_params = getSetItemParams(restored_item)
+ restored_item_params.position = round(restored_item_params.position, _api_time_value_decimal_resolution)
+ restored_item_params.end_point = round(restored_item_params.end_point, _api_time_value_decimal_resolution)
+ restored_item_ends_before_parent = restored_item_params.end_point < sizing_params.position
+ restored_item_starts_before_parent = restored_item_params.position < sizing_params.position
+ restored_item_ends_later_than_parent = restored_item_params.end_point > sizing_params.end_point
+ restored_item_starts_after_parent = restored_item_params.position > sizing_params.end_point
+
+ return restored_item_params, restored_item_ends_before_parent, restored_item_starts_before_parent, restored_item_ends_later_than_parent, restored_item_starts_after_parent
+end
+
+
+function cropItemStartingBeforeParent(restored_item, restored_item_params, sizing_params)
+ local restored_item_cropped_position_delta, restored_item_active_take, restored_vs_sizing_item_length_delta, restored_item_new_length
+
+ restored_item_cropped_position_delta = sizing_params.position - restored_item_params.position
+ restored_item_active_take = reaper.GetTake(restored_item, restored_item_params.active_take_num)
+
+ reaper.SetMediaItemPosition(restored_item, sizing_params.position, true)
+ reaper.SetMediaItemTakeInfo_Value(restored_item_active_take, _api_take_src_offset_key, restored_item_cropped_position_delta)
+
+ restored_item_params.length = reaper.GetMediaItemInfo_Value(restored_item, _api_item_length_key)
+ sizing_params.length = sizing_params.end_point - sizing_params.position
+ restored_vs_sizing_item_length_delta = restored_item_params.length - sizing_params.length
+
+ if restored_vs_sizing_item_length_delta > 0 then
+ restored_item_new_length = restored_item_params.length - restored_vs_sizing_item_length_delta
reaper.SetMediaItemLength(restored_item, restored_item_new_length, false)
end
end
+function getSetItemParams(item, params)
+ local get, set, track, retval, track_guid, active_take, active_take_num, item_params
+
+ get = not params
+ set = params
+
+ if get then
+ track = reaper.GetMediaItemTrack(item)
+ retval, track_guid = reaper.GetSetMediaTrackInfo_String(track, "GUID", "", false)
+ active_take = reaper.GetActiveTake(item)
+
+ if active_take then
+ active_take_num = reaper.GetMediaItemTakeInfo_Value(active_take, _api_takenumber_key)
+ end
+
+ item_params = {
+ ["item_guid"] = reaper.BR_GetMediaItemGUID(item),
+ ["state"] = getSetItemStateChunk(item),
+ ["track_guid"] = track_guid,
+ ["active_take_num"] = active_take_num,
+ ["position"] = reaper.GetMediaItemInfo_Value(item, _api_item_position_key),
+ ["length"] = reaper.GetMediaItemInfo_Value(item, _api_item_length_key),
+ ["instance_pool_id"] = storeRetrieveItemData(item, _instance_pool_id_key_suffix),
+ ["parent_pool_id"] = storeRetrieveItemData(item, _parent_pool_id_key_suffix)
+ }
+ item_params.end_point = item_params.position + item_params.length
+
+ if active_take then
+ item_params.source_offset = reaper.GetMediaItemTakeInfo_Value(active_take, _api_take_src_offset_key)
+ end
+
+ return item_params
+
+ elseif set then
+ reaper.SetMediaItemInfo_Value(item, _api_item_position_key, params.position)
+ reaper.SetMediaItemInfo_Value(item, _api_item_length_key, params.length)
+ end
+end
+
+
function glueSelectedItemsIntoSuperitem()
local increase_channel_count_from_take_fx, superitem
@@ -1668,21 +1809,22 @@ end
function handlePostGlue(selected_items, pool_id, first_selected_item_name, superitem, child_instances_pool_ids, sizing_params, selected_items_length, this_is_reglue, this_is_parent_update, time_selection_was_set_by_code)
- local user_selected_instance_is_being_reglued, superitem_init_name
+ local superitem_init_name
- user_selected_instance_is_being_reglued = not this_is_parent_update
superitem_init_name = handleAddtionalItemCountLabel(selected_items, pool_id, first_selected_item_name)
handleSuperitemPostGlue(superitem, superitem_init_name, pool_id, selected_items_length, this_is_reglue)
handleDescendantPoolReferences(pool_id, child_instances_pool_ids)
- if user_selected_instance_is_being_reglued then
+ if not this_is_parent_update then
handleParentPoolReferencesInChildPools(pool_id, child_instances_pool_ids)
end
if time_selection_was_set_by_code then
setResetGlueTimeSelection(sizing_params, "reset")
end
+
+ deleteContainedItemsOutsizeSizingRegion()
end
@@ -1739,46 +1881,6 @@ function handleSuperitemPostGlue(superitem, superitem_init_name, pool_id, select
end
-function getSetItemParams(item, params)
- local get, set, track, retval, track_guid, active_take, active_take_num, item_params
-
- get = not params
- set = params
-
- if get then
- track = reaper.GetMediaItemTrack(item)
- retval, track_guid = reaper.GetSetMediaTrackInfo_String(track, "GUID", "", false)
- active_take = reaper.GetActiveTake(item)
-
- if active_take then
- active_take_num = reaper.GetMediaItemTakeInfo_Value(active_take, _api_takenumber_key)
- end
-
- item_params = {
- ["item_guid"] = reaper.BR_GetMediaItemGUID(item),
- ["state"] = getSetItemStateChunk(item),
- ["track_guid"] = track_guid,
- ["active_take_num"] = active_take_num,
- ["position"] = reaper.GetMediaItemInfo_Value(item, _api_item_position_key),
- ["length"] = reaper.GetMediaItemInfo_Value(item, _api_item_length_key),
- ["instance_pool_id"] = storeRetrieveItemData(item, _instance_pool_id_key_suffix),
- ["parent_pool_id"] = storeRetrieveItemData(item, _parent_pool_id_key_suffix)
- }
- item_params.end_point = item_params.position + item_params.length
-
- if active_take then
- item_params.source_offset = reaper.GetMediaItemTakeInfo_Value(active_take, _api_take_src_offset_key)
- end
-
- return item_params
-
- elseif set then
- reaper.SetMediaItemInfo_Value(item, _api_item_position_key, params.position)
- reaper.SetMediaItemInfo_Value(item, _api_item_length_key, params.length)
- end
-end
-
-
function setSuperitemName(item, superitem_name_ending)
local take, new_superitem_name
@@ -1925,6 +2027,23 @@ function storeParentPoolReferencesInChildPool(preglue_child_instance_pool_id, ac
end
+function deleteContainedItemsOutsizeSizingRegion()
+ local i, this_contained_item_outside, this_contained_item_track
+
+ if _contained_items_outside then
+
+ for i = 1, #_contained_items_outside do
+ this_contained_item_outside = _contained_items_outside[i]
+ this_contained_item_track = reaper.GetMediaItem_Track(this_contained_item_outside)
+
+ reaper.DeleteTrackMediaItem(this_contained_item_track, this_contained_item_outside)
+ end
+ end
+
+ _contained_items_outside = nil
+end
+
+
function handleReglue(selected_items, first_selected_item_track, restored_items_pool_id)
local superitem_last_glue_params, retval, all_pool_ids_with_active_sizing_regions, sizing_region_guid, superitem, superitem_params
@@ -2013,7 +2132,7 @@ function restoreSuperitemState(superitem, superitem_params)
getSetItemStateChunk(superitem, superitem_last_glue_state)
getSetItemAudioSrc(superitem, superitem_params.updated_src)
getSetItemParams(superitem, superitem_params)
- reaper.SetMediaItemTakeInfo_Value(active_take, _api_take_src_offset_key, _src_offset_reset_value)
+ reaper.SetMediaItemTakeInfo_Value(active_take, _api_take_src_offset_key, _src_offset_default_value)
end
return superitem
@@ -2324,6 +2443,9 @@ function handleRestoredItem(active_track, stored_item_state, superitem_preedit_p
reaper.SetMediaItemSelected(restored_item, true)
restored_instance_pool_id = storeRetrieveItemData(restored_item, _instance_pool_id_key_suffix)
+
+ handleRestoredItemImage(restored_item, restored_instance_pool_id, action)
+
this_is_first_edit_after_auto_depool = not restored_instance_pool_id or restored_instance_pool_id == ""
if this_is_first_edit_after_auto_depool then
@@ -2336,8 +2458,6 @@ function handleRestoredItem(active_track, stored_item_state, superitem_preedit_p
storeRetrieveItemData(restored_item, _parent_pool_id_key_suffix, "")
end
- handleRestoredItemImage(restored_item, restored_instance_pool_id, action)
-
if restored_item_negative_position_delta then
if not restored_instances_near_project_start[restored_instance_pool_id] then
@@ -2370,7 +2490,6 @@ function handleRestoredInstanceNearProjectStart(superitem, instance_params)
restored_instance_last_glue_delta_to_parent = storeRetrieveItemData(instance_params.item, _item_offset_to_superitem_position_key_suffix)
restored_instance_last_glue_delta_to_parent = tonumber(restored_instance_last_glue_delta_to_parent)
instance_adjusted_position = superitem_params.position + restored_instance_last_glue_delta_to_parent + instance_params.negative_position_delta
-
instance_is_closer_to_project_start_than_negative_position_change = instance_adjusted_position < -instance_params.negative_position_delta
if instance_is_closer_to_project_start_than_negative_position_change then
@@ -2722,7 +2841,7 @@ function handleActivePoolSiblingPosition(sibling, sibling_active_take, user_want
reaper.SetMediaItemPosition(sibling, sibling_adjusted_position, false)
if user_wants_source_position_maintained then
- reaper.SetMediaItemTakeInfo_Value(sibling_active_take, _api_take_src_offset_key, _src_offset_reset_value)
+ reaper.SetMediaItemTakeInfo_Value(sibling_active_take, _api_take_src_offset_key, _src_offset_default_value)
end
sibling_position_change_affect_on_length = 0
@@ -2769,7 +2888,7 @@ function propagatePositionOnSiblingNearProjectStart(sibling, sibling_active_take
local sibling_src_offset_adjustment_delta, sibling_adjusted_src_offset, sibling_position_change_affect_on_length
- if sibling_active_take_playrate ~= 1 then
+ if sibling_active_take_playrate ~= _take_playrate_default_value then
sibling_src_offset_adjustment_delta = (-sibling_current_position * sibling_active_take_playrate) - _superitem_instance_offset_delta_since_last_glue
else
@@ -2794,12 +2913,12 @@ function adjustActivePoolSiblingSourcePosition(sibling, sibling_active_take, sib
local sibling_adjusted_src_offset
if user_wants_position_propagation then
- sibling_adjusted_src_offset = 0
+ sibling_adjusted_src_offset = _src_offset_default_value
- if sibling_active_take_playrate ~= 1 then
+ if sibling_active_take_playrate ~= _take_playrate_default_value then
sibling_adjusted_src_offset = (_superitem_instance_offset_delta_since_last_glue * sibling_active_take_playrate) - _superitem_instance_offset_delta_since_last_glue
- if sibling_current_src_offset ~= 0 then
+ if sibling_current_src_offset ~= _src_offset_default_value then
sibling_adjusted_src_offset = sibling_adjusted_src_offset + sibling_current_src_offset - (sibling_current_src_offset * sibling_active_take_playrate)
end
end
@@ -3156,7 +3275,7 @@ end
function handleEditOrUnglue(pool_id, action)
- local superitem, undo_block_string
+ local superitem, undo_block_string, active_track, restored_items
superitem = getFirstSelectedItem()
@@ -3169,11 +3288,13 @@ function handleEditOrUnglue(pool_id, action)
undo_block_string = _unglue_undo_block_string
end
- processEditOrUnglue(superitem, pool_id, action)
+ active_track, restored_items = processEditOrUnglue(superitem, pool_id, action)
if action ~= "DePool" then
cleanUpAction(undo_block_string)
end
+
+ itemsAreOffscreen(#restored_items, action)
end
@@ -3514,6 +3635,7 @@ function handleDePoolPostGlue(superitem, target_item_state, target_item_params)
getSetItemStateChunk(superitem, target_item_state)
getSetItemName(superitem, active_take_name)
storeRetrieveItemData(superitem, _instance_pool_id_key_suffix, new_pool_id)
+ reaper.SetMediaItemSelected(superitem, true)
setSuperitemColor()
return new_pool_id