MetaRamp TOP - 2022-01-17 23:09

MetaRamp TOP

Link to main site

@KaeganCasey Thanks for post here in the asset-community as well, makes it easier for everyone to find these tools!

@ben Anytime!! If you use it please let me know if you have any ideas for how it could be improved!

Very cool component @KaeganCasey!

Feedback here is intended with the utmost respect for sharing your work - our community thrives on individuals who are willing to share what they’ve made. These are just some thoughts / observations that you can take with a grain of salt.

Optimziations

I love a little simplicity when I can find it - one thought for you here is to simplify how you’re fetching your color parameters:

By using a script DAT instead.


# called whenever custom pulse parameter is pushed
def onPulse(par):
	return

def onCook(scriptOp):
	scriptOp.clear()
	rows = []
	header = ['pos', 'r', 'g', 'b', 'a']
	rows.append(header)

	# loop through each position par and build a list of position, r, g, b, a values
	for each in parent().pars('Position*'):

		pos = each.eval()

		# because your position and color pars share a digit we can rely on this order
		# when buidling our our color keys
		par_digit = get_digit(each)
		red = parent.META_RAMP.par[f'Color{par_digit}r']
		green = parent.META_RAMP.par[f'Color{par_digit}g']
		blue = parent.META_RAMP.par[f'Color{par_digit}b']
		alpha = parent.META_RAMP.par[f'Color{par_digit}a']

		rows.append([pos, red, green, blue, alpha])

	# loop though all elements in your rows and append to your script dat
	for each_row in rows:
		scriptOp.appendRow(each_row)

	return


def get_digit(par):
	return tdu.digits(par.name)

You can simplify your component down to these ops to handle the ramp building:

You can also use a single par execute DAT with some control flow statements, or a function map.
You could also skip your reordering DATs and watch for changes to Position pars to call your reorder method.

Control flow style approach would look like:

def onValueChange(par, prev):
	# use par.eval() to get current value
	if par.name == 'Enabledelete':
		parent.META_RAMP.OnEnableDelete(par)

	elif 'Position' in par.name:
		print(par.name)
		parent.META_RAMP.SwitchKeyPositions()
	else:
		pass
		
	return

# Called at end of frame with complete list of individual parameter changes.
# The changes are a list of named tuples, where each tuple is (Par, previous value)
def onValuesChanged(changes):
	for c in changes:
		# use par.eval() to get current value
		par = c.par
		prev = c.prev
	return

def onPulse(par):
	if par.name == 'Addkey':
		parent.META_RAMP.OnAddKey()
	
	elif 'Delete' in par.name:
		parent.META_RAMP.OnDeleteKey(par)
	else:
		pass
	return

Those changes reduce your op foot print down to this:

Additions

I often like also having the ramp keys as CHOP channels, so you might consider adding another output from your op that was the table data converted into CHOP Data:

I’d also consider adding a toggle to allow par re-ordering- no joke that would trip me up if I was scripting changes to this comp. It is for sure, :100: awsome… but also a little mind bending to watch pars re-arrange themselves.

Edge Cases

My partner loves to break any component I make, which has taught me a TON about user testing. One thing to chew on is the edge case where your Position99 par gets moved to a position that is not 1 in the ramp. Because this par’s Delete pulse is inactive, you can’t remove this ramp key:

image

In this case, the user instead needs to instead:

  • change Position99 to a value of 1
  • change the Color values of the Position99 to match Position4
  • delete the Position4 key

Not at all a deal breaker, but worth ruminating about. If nothing else you might include a note about the Component's Ideocracies, or intended workflow to give users a heads about how the pars work.

A reasonable change here would be to lock the value of Position99 just like you do with Position0 - that makes everything between them re-arrangeable, but keeps your start and end pars locked. I realize that produces some other edge cases… so it might be a matter of choosing the way you’d like to work.

@raganmd Thank you so much for such detailed feedback!! I am blown away!!! I will let all of this sink in and begin implementing some of these awesome ideas tonight!! Thank you for taking the time to look at this so closely! Excited to learn from what you’ve said here!

@KaeganCasey Thank you for a very useful comp.

When I drive any of the keys Color parameter with an expression, such as oscillating the alpha, the internal ramp does not update!

ALSO: Create 9 keys, set ramp type Vertical, notches Step and note that the final notch (1) does not appear. Is this normal for the ramp? I’d expect all colors to appear.

1 Like

Hello @aaauser1969 I have the same issue as you.
If I connect the rgb values with moving value it’s not updating the color, but if I connect the rgb values with midi slider it’s updating correctly …
I have found a solution:
Inside the base “MetaRamp” I have create a “CHOP Execute”, with this code :

def whileOn(channel, sampleIndex, val, prev):
	op('script1').par.setuppars.pulse()
	return

I create a const CHOP set to 1, and drag it into the param “CHOPs” of the “CHOP Execute” dans activate the param “Whle ON” to ON

1 Like

Hey! Nice fix for a great comp @KaeganCasey .
Merci

1 Like