New script to build two versions of the package for Max 8 and Max 9 based on prefix in filenames.

This commit is contained in:
2025-10-09 15:05:37 +02:00
parent ea35d06437
commit a003206b63
7 changed files with 310 additions and 200 deletions

3
.gitignore vendored
View File

@@ -1,4 +1,5 @@
.DS_Store .DS_Store
.AppleDouble .AppleDouble
.LSOverride .LSOverride
media/ media/
dist/

109
build.sh Executable file
View File

@@ -0,0 +1,109 @@
#!/bin/bash
# Max Package Build Script
# Builds version-specific packages for Max 8 and Max 9
# Generated by Claude Sonnet 4.5
set -e # Exit on error
# Configuration
PACKAGE_NAME="tc.preset"
DIST_DIR="./dist"
MAX8_DIR="$DIST_DIR/Max 8/$PACKAGE_NAME"
MAX9_DIR="$DIST_DIR/Max 9/$PACKAGE_NAME"
INSTALL_MAX8="$HOME/Documents/Max 8/Packages/$PACKAGE_NAME"
INSTALL_MAX9="$HOME/Documents/Max 9/Packages/$PACKAGE_NAME"
echo "Building Max packages..."
# Clean and create dist directories
rm -rf "$DIST_DIR"
mkdir -p "$MAX8_DIR"
mkdir -p "$MAX9_DIR"
# Function to copy files recursively
copy_files() {
local target_dir=$1
local prefix=$2
# Find all files (not directories) in the repo
find . -type f \
-not -path "*/.*" \
-not -path "./dist/*" \
-not -name "build.sh" | while read -r file; do
# Get filename without path
local filename=$(basename "$file")
# Get relative path from repo root
local relpath="${file#./}"
local dirpath=$(dirname "$relpath")
# Determine if file should be copied to this version
if [[ $filename == max8.* ]] && [[ $prefix == "max8" ]]; then
# Remove max8. prefix and copy
local newname="${filename#max8.}"
local target="$target_dir/$dirpath/$newname"
mkdir -p "$(dirname "$target")"
cp "$file" "$target"
echo "$relpath (as $dirpath/$newname) [Max 8]"
elif [[ $filename == max9.* ]] && [[ $prefix == "max9" ]]; then
# Remove max9. prefix and copy
local newname="${filename#max9.}"
local target="$target_dir/$dirpath/$newname"
mkdir -p "$(dirname "$target")"
cp "$file" "$target"
echo "$relpath (as $dirpath/$newname) [Max 9]"
elif [[ $filename != max8.* ]] && [[ $filename != max9.* ]]; then
# Copy shared files to both versions
local target="$target_dir/$relpath"
mkdir -p "$(dirname "$target")"
cp "$file" "$target"
echo "$relpath [shared]"
fi
done
}
echo ""
echo "Building Max 8 version..."
copy_files "$MAX8_DIR" "max8"
echo ""
echo "Building Max 9 version..."
copy_files "$MAX9_DIR" "max9"
echo ""
echo "Build complete!"
echo ""
echo "Max 8 package: $MAX8_DIR"
echo "Max 9 package: $MAX9_DIR"
echo ""
# Ask to install
read -p "Install to Max Packages folders (~/Documents/Max <8|9>/Packages)? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "Installing packages..."
# Create Packages directories if they don't exist
mkdir -p "$HOME/Documents/Max 8/Packages"
mkdir -p "$HOME/Documents/Max 9/Packages"
# Copy to Max 8
if [ -d "$INSTALL_MAX8" ]; then
rm -rf "$INSTALL_MAX8"
fi
cp -r "$MAX8_DIR" "$INSTALL_MAX8"
echo "✓ Installed to $INSTALL_MAX8"
# Copy to Max 9
if [ -d "$INSTALL_MAX9" ]; then
rm -rf "$INSTALL_MAX9"
fi
cp -r "$MAX9_DIR" "$INSTALL_MAX9"
echo "✓ Installed to $INSTALL_MAX9"
echo ""
echo "Installation complete!"
else
echo "Skipped installation."
fi

View File

@@ -6,7 +6,7 @@
A jsui replacement for the preset object. A jsui replacement for the preset object.
</digest> </digest>
<description> <description>
tc.preset is a jsui clone of the preset object, but loaded with more features, such as preset organization through drag and drop, display as a scrollable list, colored slots... tc.preset is a <o>jsui</o>/<o>v8ui</o> clone of the <o>preset</o> object, but loaded with more features, such as preset organization through drag and drop, display as a scrollable list, colored slots...
Contrary to the preset object, tc.preset doesn't work alone and has to be used in conjonction with a pattrstorage object.<modification class=""></modification> Contrary to the preset object, tc.preset doesn't work alone and has to be used in conjonction with a pattrstorage object.<modification class=""></modification>
</description> </description>

View File

@@ -0,0 +1,3 @@
max setdefinepackage tc.preset pattrstorage;
max definesubstitution tc.preset jsui @filename tc.preset;
max setdefinepackage "" "";

View File

@@ -0,0 +1,3 @@
max setdefinepackage tc.preset pattrstorage;
max define tc.preset v8ui @filename tc.preset;
max setdefinepackage "" "";

View File

@@ -1,2 +0,0 @@
max objectfile tc.preset tc.preset;
max definesubstitution tc.preset jsui @filename tc.preset;

View File

@@ -380,32 +380,30 @@ function paint_base() {
bg_width = layout == 0 ? columns * (slot_size + spacing) - spacing + 2 * margin : ui_width; bg_width = layout == 0 ? columns * (slot_size + spacing) - spacing + 2 * margin : ui_width;
bg_height = rows * (slot_size + spacing) - spacing + 2 * margin; bg_height = rows * (slot_size + spacing) - spacing + 2 * margin;
mg = new MGraphics(ui_width*2, bg_height*2); mg = new MGraphics(ui_width*2, bg_height*2);
with(mg) { mg.set_source_rgba(background_color);
set_source_rgba(background_color); mg.rectangle(0, 0, bg_width*2, bg_height*2);
rectangle(0, 0, bg_width*2, bg_height*2); mg.fill();
fill();
select_font_face(font_name); mg.select_font_face(font_name);
set_font_size(font_size); mg.set_font_size(font_size);
// All slots // All slots
for (var i = 1; i <= true_slots_count_display; i++) { for (var i = 1; i <= true_slots_count_display; i++) {
if (i != drag_slot) { //We mask the slot that is currently dragged as it is drawn at the mouse position already if (i != drag_slot) { //We mask the slot that is currently dragged as it is drawn at the mouse position already
if (slots[i].name != null) { if (slots[i].name != null) {
if (color_mode == 1) { if (color_mode == 1) {
set_source_rgba(color_wheel_custom[i % color_wheel_size]); mg.set_source_rgba(color_wheel_custom[i % color_wheel_size]);
} else if (color_mode == 2) { } else if (color_mode == 2) {
set_source_rgba(color_wheel_custom[Math.abs(slots[i].color_index) % color_wheel_size]); mg.set_source_rgba(color_wheel_custom[Math.abs(slots[i].color_index) % color_wheel_size]);
} else if (color_mode == 3) { } else if (color_mode == 3) {
set_source_rgba(slots[i].color_custom); mg.set_source_rgba(slots[i].color_custom);
} else {
set_source_rgba(stored_slot_color);
}
} else { } else {
set_source_rgba(empty_slot_color); mg.set_source_rgba(stored_slot_color);
} }
draw_slot(i, 2, mg); } else {
mg.set_source_rgba(empty_slot_color);
} }
draw_slot(i, 2, mg);
} }
} }
is_painting_base = 0; is_painting_base = 0;
@@ -423,186 +421,182 @@ function paint()
onresize(cur_size[0], cur_size[1]); onresize(cur_size[0], cur_size[1]);
} else { } else {
// post("redraw\n"); // post("redraw\n");
with (mgraphics) { mgraphics.select_font_face(font_name);
select_font_face(font_name); mgraphics.set_font_size(font_size);
set_font_size(font_size); mgraphics.translate(0, y_offset);
translate(0, y_offset); // Draw the base, which includes empty and filled slots
// Draw the base, which includes empty and filled slots // It is first rendered at twice the size in order to make texts look nice and cripsy on hidpi discplays
// It is first rendered at twice the size in order to make texts look nice and cripsy on hidpi discplays // So we need to scale it down here
// So we need to scale it down here mgraphics.scale(0.5, 0.5);
scale(0.5, 0.5); mgraphics.image_surface_draw(base_drawing);
image_surface_draw(base_drawing); mgraphics.scale(2, 2);
scale(2, 2);
mgraphics.set_line_width(1);
// Active slot
if (is_dragging == 0 && active_slot > 0 && active_slot <= slots_count_display) {
mgraphics.set_source_rgba(active_slot_color);
if (color_mode) {
draw_slot_bubble(slots[active_slot].left+1.5, slots[active_slot].top+1.5, slot_size-3, slot_size-3);
mgraphics.set_line_width(3);
mgraphics.stroke();
} else {
draw_slot_bubble(slots[active_slot].left, slots[active_slot].top, slot_size, slot_size);
mgraphics.fill();
}
}
// Previous active slot
if (is_dragging == 0 && previous_active_slot > 0 && previous_active_slot <= slots_count_display) {
mgraphics.set_source_rgba(active_slot_color[0], active_slot_color[1], active_slot_color[2], active_slot_color[3] * 0.5);
if (color_mode) {
draw_slot_bubble(slots[previous_active_slot].left+1.5, slots[previous_active_slot].top+1.5, slot_size-3, slot_size-3);
mgraphics.set_line_width(3);
mgraphics.stroke();
} else {
draw_slot_bubble(slots[previous_active_slot].left, slots[previous_active_slot].top, slot_size, slot_size);
mgraphics.fill();
}
}
//Hide dragged slot
if (is_dragging) {
mgraphics.set_source_rgba(empty_slot_color);
draw_slot_bubble(slots[drag_slot].left, slots[drag_slot].top, slot_size, slot_size);
mgraphics.fill();
}
// Selected slot
if (selected_slot > 0 && selected_slot <= slots_count_display) {
mgraphics.set_source_rgba(active_slot_color);
mgraphics.set_line_width(1);
draw_slot_bubble(slots[selected_slot].left - 0.5, slots[selected_slot].top - 0.5, slot_size + 1, slot_size + 1);
mgraphics.stroke();
}
// Interpolated slots
if (is_dragging == 0 && display_interp && is_interpolating) {
set_line_width(1); for (var i = 1; i <= slots_count_display; i++) {
var interp = slots[i].interp;
if (interp >= 0) {
mgraphics.set_source_rgba(interp_slot_color);
draw_slot_bubble(slots[i].left, slots[i].top, slot_size, slot_size);
mgraphics.stroke();
draw_slot_bubble(slots[i].left, slots[i].top + slot_size * (1-interp), slot_size, slot_size * interp);
mgraphics.fill();
}
}
}
//Edited dot
if (active_slot_edited && active_slot > 0 && selected_slot <= slots_count_display) {
mgraphics.set_source_rgba(edited_color);
mgraphics.ellipse(slots[active_slot].left + 1, slots[active_slot].top + 1, slot_size/3, slot_size/3);
mgraphics.fill();
}
// Hovered slot
if (last_hovered > -1) {
if (shift_hold && last_hovered_is_preset_slot) {
if (option_hold) {
// About to delete
mgraphics.set_source_rgba(empty_slot_color[0], empty_slot_color[1], empty_slot_color[2], 0.8);
draw_slot_bubble(slots[last_hovered].left + 1, slots[last_hovered].top + 1, slot_size-2, slot_size-2);
mgraphics.fill();
} else {
// About to store
mgraphics.set_source_rgba(active_slot_color[0], active_slot_color[1], active_slot_color[2], 0.7);
draw_slot_bubble(slots[last_hovered].left + 1, slots[last_hovered].top + 1, slot_size-2, slot_size-2);
mgraphics.fill();
}
}
// Slot border
mgraphics.set_source_rgba(1, 1, 1, 0.8);
draw_slot_bubble(slots[last_hovered].left, slots[last_hovered].top, slot_size, slot_size);
mgraphics.stroke();
if (layout == 0) {
//Text (slot number and name)
var text = null;
if (scrollable && nbslot_edit && (last_hovered > (true_slots_count_display - 2))) {
if (last_hovered == true_slots_count_display - 1) {
text = "remove slot row";
} else {
text = "add slot row";
}
} else {
text = format_slot_name(last_hovered);
}
var text_dim = mgraphics.text_measure(text);
// If the text is too big or a slot is being dragged, display the text on top of the next slot.
// Otherwise, it gets displayed on the hovered slot.
var bg_txt_dim_w = text_dim[0] > slot_size ? text_dim[0] + 4 : slot_size + 4;
var bg_txt_dim_h = text_dim[1] > slot_size ? text_dim[1] + 4 : slot_size + 4;
var bg_txt_pos_x = text_dim[0] > slot_size || is_dragging ? slots[last_hovered].left + slot_size + 2: slots[last_hovered].left - 2;
var bg_txt_pos_y = text_dim[1] > slot_size || is_dragging ? slots[last_hovered].top - 2 : slots[last_hovered].top - 2;
// If there is not enough place on the right and if there is more available place on the left, text is displayed on the left
if (bg_txt_pos_x + bg_txt_dim_w > ui_width && slots[last_hovered].left - half_spacing > ui_width - slots[last_hovered].right) {
bg_txt_pos_x = slots[last_hovered].left - half_spacing - bg_txt_dim_w;
}
var txt_pos_x = text_dim[0] > slot_size ? bg_txt_pos_x + half_spacing : bg_txt_pos_x + (bg_txt_dim_w / 2) - (text_dim[0]/2);
var txt_pos_y = bg_txt_pos_y + (bg_txt_dim_h + text_dim[1]) / 2 - text_dim[1]*0.18;
// Bubble background
mgraphics.set_source_rgba(text_bg_color);
mgraphics.rectangle_rounded(bg_txt_pos_x, bg_txt_pos_y, bg_txt_dim_w, bg_txt_dim_h, 4, 4);
mgraphics.fill();
// Buble text
mgraphics.set_source_rgba(text_color);
mgraphics.move_to(txt_pos_x, txt_pos_y);
mgraphics.show_text(text.toString());
}
// Active slot }
if (is_dragging == 0 && active_slot > 0 && active_slot <= slots_count_display) {
set_source_rgba(active_slot_color); // Drag slot
if (color_mode) { if (is_dragging) {
draw_slot_bubble(slots[active_slot].left+1.5, slots[active_slot].top+1.5, slot_size-3, slot_size-3); if (layout == 0) {
set_line_width(3); mgraphics.translate(last_x, last_y );
stroke(); mgraphics.rotate(0.15);
} else { mgraphics.scale(1.1, 1.1);
draw_slot_bubble(slots[active_slot].left, slots[active_slot].top, slot_size, slot_size);
fill(); // Slot shadow
mgraphics.set_source_rgba(0, 0, 0, 0.15);
for (var i = 0; i<4; i++) {
draw_slot_bubble( i*0.4 + 1-slot_size/2, i*0.4 + 1-slot_size/2, slot_size + i*0.8, slot_size+i*0.8);
mgraphics.fill();
} }
} draw_slot_bubble( 2-slot_size/2, 2-slot_size/2, slot_size, slot_size);
mgraphics.fill();
// Previous active slot //Flying slot
if (is_dragging == 0 && previous_active_slot > 0 && previous_active_slot <= slots_count_display) { mgraphics.set_source_rgba(active_slot_color);
set_source_rgba(active_slot_color[0], active_slot_color[1], active_slot_color[2], active_slot_color[3] * 0.5); draw_slot_bubble( -slot_size/2, -slot_size/2, slot_size, slot_size);
if (color_mode) { mgraphics.fill();
draw_slot_bubble(slots[previous_active_slot].left+1.5, slots[previous_active_slot].top+1.5, slot_size-3, slot_size-3); } else {
set_line_width(3); mgraphics.translate(last_x, last_y );
stroke(); // rotate(0.15);
} else { mgraphics.set_source_rgba(active_slot_color);
draw_slot_bubble(slots[previous_active_slot].left, slots[previous_active_slot].top, slot_size, slot_size);
fill();
}
}
//Hide dragged slot
if (is_dragging) {
set_source_rgba(empty_slot_color);
draw_slot_bubble(slots[drag_slot].left, slots[drag_slot].top, slot_size, slot_size);
fill();
}
// Selected slot
if (selected_slot > 0 && selected_slot <= slots_count_display) {
set_source_rgba(active_slot_color);
set_line_width(1);
draw_slot_bubble(slots[selected_slot].left - 0.5, slots[selected_slot].top - 0.5, slot_size + 1, slot_size + 1);
stroke();
}
// Interpolated slots
if (is_dragging == 0 && display_interp && is_interpolating) {
for (var i = 1; i <= slots_count_display; i++) { draw_slot_bubble( -slot_size/2, -slot_size/2, slot_size, slot_size);
var interp = slots[i].interp; mgraphics.fill();
if (interp >= 0) { // slot name
set_source_rgba(interp_slot_color); var text = format_slot_name(drag_slot);
draw_slot_bubble(slots[i].left, slots[i].top, slot_size, slot_size); var bg_txt_pos_x = slot_size/2+ spacing;
stroke(); var bg_txt_pos_y = -slot_size/2;
draw_slot_bubble(slots[i].left, slots[i].top + slot_size * (1-interp), slot_size, slot_size * interp); var bg_txt_dim_w = ui_width - (2*margin + slot_size + spacing);
fill(); var bg_txt_dim_h = slot_size;
} mgraphics.set_source_rgba(stored_slot_color);
} draw_text_bubble(bg_txt_pos_x, bg_txt_pos_y, bg_txt_dim_w, bg_txt_dim_h, text);
} }
//Edited dot
if (active_slot_edited && active_slot > 0 && selected_slot <= slots_count_display) {
set_source_rgba(edited_color);
ellipse(slots[active_slot].left + 1, slots[active_slot].top + 1, slot_size/3, slot_size/3);
fill();
}
// Hovered slot
if (last_hovered > -1) {
if (shift_hold && last_hovered_is_preset_slot) {
if (option_hold) {
// About to delete
set_source_rgba(empty_slot_color[0], empty_slot_color[1], empty_slot_color[2], 0.8);
draw_slot_bubble(slots[last_hovered].left + 1, slots[last_hovered].top + 1, slot_size-2, slot_size-2);
fill();
} else {
// About to store
set_source_rgba(active_slot_color[0], active_slot_color[1], active_slot_color[2], 0.7);
draw_slot_bubble(slots[last_hovered].left + 1, slots[last_hovered].top + 1, slot_size-2, slot_size-2);
fill();
}
}
// Slot border
set_source_rgba(1, 1, 1, 0.8);
draw_slot_bubble(slots[last_hovered].left, slots[last_hovered].top, slot_size, slot_size);
stroke();
if (layout == 0) {
//Text (slot number and name)
var text = null;
if (scrollable && nbslot_edit && (last_hovered > (true_slots_count_display - 2))) {
if (last_hovered == true_slots_count_display - 1) {
text = "remove slot row";
} else {
text = "add slot row";
}
} else {
text = format_slot_name(last_hovered);
}
var text_dim = text_measure(text);
// If the text is too big or a slot is being dragged, display the text on top of the next slot.
// Otherwise, it gets displayed on the hovered slot.
var bg_txt_dim_w = text_dim[0] > slot_size ? text_dim[0] + 4 : slot_size + 4;
var bg_txt_dim_h = text_dim[1] > slot_size ? text_dim[1] + 4 : slot_size + 4;
var bg_txt_pos_x = text_dim[0] > slot_size || is_dragging ? slots[last_hovered].left + slot_size + 2: slots[last_hovered].left - 2;
var bg_txt_pos_y = text_dim[1] > slot_size || is_dragging ? slots[last_hovered].top - 2 : slots[last_hovered].top - 2;
// If there is not enough place on the right and if there is more available place on the left, text is displayed on the left
if (bg_txt_pos_x + bg_txt_dim_w > ui_width && slots[last_hovered].left - half_spacing > ui_width - slots[last_hovered].right) {
bg_txt_pos_x = slots[last_hovered].left - half_spacing - bg_txt_dim_w;
}
var txt_pos_x = text_dim[0] > slot_size ? bg_txt_pos_x + half_spacing : bg_txt_pos_x + (bg_txt_dim_w / 2) - (text_dim[0]/2);
var txt_pos_y = bg_txt_pos_y + (bg_txt_dim_h + text_dim[1]) / 2 - text_dim[1]*0.18;
// Bubble background
set_source_rgba(text_bg_color);
rectangle_rounded(bg_txt_pos_x, bg_txt_pos_y, bg_txt_dim_w, bg_txt_dim_h, 4, 4);
fill();
// Buble text
set_source_rgba(text_color);
move_to(txt_pos_x, txt_pos_y);
show_text(text.toString());
}
}
// Drag slot
if (is_dragging) {
if (layout == 0) {
translate(last_x, last_y );
rotate(0.15);
scale(1.1, 1.1);
// Slot shadow
set_source_rgba(0, 0, 0, 0.15);
for (var i = 0; i<4; i++) {
draw_slot_bubble( i*0.4 + 1-slot_size/2, i*0.4 + 1-slot_size/2, slot_size + i*0.8, slot_size+i*0.8);
fill();
}
draw_slot_bubble( 2-slot_size/2, 2-slot_size/2, slot_size, slot_size);
fill();
//Flying slot
set_source_rgba(active_slot_color);
draw_slot_bubble( -slot_size/2, -slot_size/2, slot_size, slot_size);
fill();
} else {
translate(last_x, last_y );
// rotate(0.15);
set_source_rgba(active_slot_color);
draw_slot_bubble( -slot_size/2, -slot_size/2, slot_size, slot_size);
fill();
// slot name
var text = format_slot_name(drag_slot);
var bg_txt_pos_x = slot_size/2+ spacing;
var bg_txt_pos_y = -slot_size/2;
var bg_txt_dim_w = ui_width - (2*margin + slot_size + spacing);
var bg_txt_dim_h = slot_size;
set_source_rgba(stored_slot_color);
draw_text_bubble(bg_txt_pos_x, bg_txt_pos_y, bg_txt_dim_w, bg_txt_dim_h, text);
}
}
} }
} }
} }
@@ -1725,7 +1719,9 @@ function get_prect(prect) {
get_prect.local = 1; get_prect.local = 1;
function notifydeleted(){ function notifydeleted(){
poll_edited_task.freepeer(); if (poll_edited_task.valid) {
poll_edited_task.freepeer();
}
} }
// ATTRIBUTES DECLARATION // ATTRIBUTES DECLARATION