Snavanced!

I am just wondering, do you have an exact date for when the mod releases? I am just wondering... :thinking:

https://en.wikipedia.org/wiki/I_Want_to_Hold_Your_Hand

@puppetia There isn't an exact date for the mod's arrival, just I'm repairing the errors and updating the mod to be like the new Snap!'s releases. (I'm a student, so that's why I'm slow.)
Thank you for responding to me. Welcome to the Snap! Forums! :slightly_smiling_face:

ohh

  1. Please don't post your age or birthdate here.

  2. I'm sure you meant this to be friendly, but "newbie" is sort of a demeaning thing to call someone, I think.

Ok, dear master. I'm just learning the rules from the text that is in your reply. Thanks. :tuit:

Great news!!! Super-Snap! is now available on my account's Google Drive as below: :smile:
https://drive.google.com/drive/folders/13gKTRkUPu_feObKN6DfgreYIeQCGqAf_?usp=sharing

Remember Super-Snap! as a beta, with the updates coming, I'm finishing the mod, any new idea can tell me to update more even if it is finished or not. You can share your own screenshots too.

Guys, I'm very curious and anxious, if you don't know, in the language options are only available english and toki+pona, toki+pona is the first language that I'm testing on the mod, I see that need more diversity to talk and program with new languages that are not in the main Snap!, so there are new manners to sense the perfect balance of the programming peace for our dear users. :heart: + :smiley:


The "linja-pona" font is needed to show the glyphs. :nerd_face:
Captura de Pantalla 2023-12-06 a la(s) 18.19.23.p. m.

Starting w/ a conlang. Nice.

Will you put it on github aswell

Well, for the new version. The current is on Google Drive for checking all of the changes. :slight_smile:
The new version will include new idioms for the mod, replacing the MIDI system with a new one,
setting perfectly the backpack, giving an option to get the old gray ring blocks from Snap!,
repairing the incorrect strings from the migrations and giving to you the new version of charts.js.
The charts.js is the giving improvement for today from MorphicV1 to MorphicV2. So you have this:

/*

	charts.js

	business charts for morphic.js

	written by Jens Mönig
	jens@moenig.org

	Copyright (C) 2024 by Jens Mönig

	charts.js is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as
	published by the Free Software Foundation, either version 3 of
	the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.


	prerequisites:
	--------------
	needs morphic.js and widgets.js


	I. hierarchy
	-------------
	the following tree lists all constructors hierarchically,
	indentation indicating inheritance. Refer to this list to get a
	contextual overview:

	Morph*
		BoxMorph*
			ChartMorph
		GridMorph
		LineMorph

	* from Morphic.js


	II. toc
	-------
	the following list shows the order in which all constructors are
	defined. Use this list to locate code in this document:

	GridMorph
	LineMorph
	ChartMorph

*/

// Global settings /////////////////////////////////////////////////////

/*global modules, newCanvas, Point, Morph, WorldMorph, Color, BoxMorph,
StringMorph, ScrollFrameMorph, MorphicPreferences, SliderMorph,
ToggleMorph, HandleMorph*/

modules.charts = '2024-January-29';

var GridMorph, LineMorph, ChartMorph;

WorldMorph.prototype.customMorphs = function () {
	// add examples to the world's demo menu
	return [
		new GridMorph,
		new ChartMorph
	];
};

// GridMorph ///////////////////////////////////////////////////////////

// I am a chart's coordinate system

// GridMorph inherits from Morph:

GridMorph.prototype = new Morph;
GridMorph.prototype.constructor = GridMorph;
GridMorph.uber = Morph.prototype;

GridMorph.prototype.colors = [
	new Color(195, 10, 0),
	new Color(0, 175, 175),
	new Color(255, 185, 50),
	new Color(100, 0, 235)
];

// GridMorph instance creation:

function GridMorph () {this.init();};

GridMorph.prototype.init = function (x, y, xLines, yLines) {
	// additional attributes:
	this.backgroundColor = new Color(30, 30, 30);

	this.xUnits = x || (x === 0 ? 0 : 14);
	this.yUnits = y || (y === 0 ? 0 : 200);
	this.xInterval = xLines || 1;
	this.yInterval = yLines || 25;

	this.axesWidth = 1;
	this.lineWidth = 1;
	this.fontSize = 10;

	this.isFilled = true;

	this.columns = [
		'1998',
		'1999',
		'2000',
		'2001',
		'2002',
		'2003',
		'2004',
		'2005',
		'2006',
		'2007',
		'2008',
		'2009',
		'2010',
		'2011',
		'2012'
	];

	this.columnInterval = 1;

	this.rows = [
		'cherries',
		'apples',
		'bananas',
		'plums'
	];

	this.lines = [
		[190, 160, 40, 120, 30, 70, 82, 130, 163, 149, 138, 112, 186, 152, 161],
		[3, 40, 30, 45, 35, 49, 37, 24, 31, 18, 74, 86, 98, 42, 37],
		[10, 180, 10, 85, 25, 79, 80, 82, 130, 64, 48, 50, 53, 78, 82],
		[40, 80, 90, 25, 15, 119, 110, 86, 75, 163, 156, 174, 23, 12, 23]
	];

	// initialize inherited attributes:
	GridMorph.uber.init.call(this);

	// override inherited attributes:
	this.isFreeForm = false;
	this.color = new Color(50, 50, 50);
	this.setExtent(new Point(950, 280));
	this.createLabels();
	this.createLines();
	this.fixLayout();
};

GridMorph.prototype.fixLayout = function () {
	var myself = this, colNo = 0,
	xunit = this.width() / this.xUnits;
	this.columnInterval = Math.max(
		Math.round(this.visibleBounds(
                 ).width() / xunit / 5), 1
	); this.children.forEach(function (m) {
		if (m instanceof LineMorph) {
			m.bounds = myself.bounds.copy();
			m.isFilled = myself.isFilled;
			m.rerender();
		} else if (m.isXLabel) {
			if (colNo % myself.columnInterval === 0) {
				m.show();
				m.setCenter(new Point(
					myself.left() + colNo * xunit,
					myself.bottom() + myself.fontSize
				));
			} else {
				m.hide();
			}; colNo += 1;
		};
	}); this.changed();
};

GridMorph.prototype.render = function (context) {
	// initialize my surface property
	var i, x, y, temp;

	temp = this.color;
	this.color = this.backgroundColor;
	GridMorph.uber.render.call(this, context);
	this.color = temp;

	context.lineWidth = this.axesWidth;
	context.strokeStyle = this.color.toString();

	// axes:
	context.beginPath();
	context.moveTo(this.axesWidth / 2, 0);
	context.lineTo(
		this.axesWidth / 2,
		this.height() - this.axesWidth / 2
	); context.lineTo(
		this.width(),
		this.height() - this.axesWidth / 2
	); context.stroke();

	context.lineWidth = this.lineWidth;

	// horizontal lines:
	if (this.yInterval) {
		for (i = 0; i <= this.yUnits; i += this.yInterval) {
			y = this.height()
				- (i * (this.height() / this.yUnits))
				+ this.lineWidth / 2;
			context.moveTo(0, y);
			context.lineTo(this.width(), y);
			context.stroke();
		};
	}; // vertical lines:
	if (this.xInterval) {
		for (i = 0; i <= this.xUnits; i += this.xInterval) {
			x = i * (this.width() / this.xUnits)
				- this.lineWidth / 2;
			context.moveTo(x, 0);
			context.lineTo(x, this.height());
			context.stroke();
		};
	}; this.fixLayout();
};

GridMorph.prototype.createLines = function () {
	var myself = this, lm, i = 0;
	this.lines.forEach(function (line) {
		lm = new LineMorph(
			myself.rows[i],
			myself.xUnits,
			myself.yUnits,
			line,
			myself.colors[i],
			this.isFilled
		); lm.setPosition(myself.position(
                 ).copy()); myself.add(lm); i += 1;
	});
};

GridMorph.prototype.createLabels = function () {
	var myself = this, lm, i = 0;

	this.columns.forEach(function (col) {
		lm = new StringMorph(
			col,
			myself.fontSize,
			null,
			true,
			false
		);
		lm.isXLabel = true;
		lm.setColor(new Color(230, 230, 230));
		myself.add(lm);
		i += 1;
	});
};

GridMorph.prototype.mouseEnter = function () {
    this.children.forEach(function (child) {
        if (child instanceof LineMorph) {
            child.startStepping();
        };
    });
};


GridMorph.prototype.mouseLeave = function () {
    this.children.forEach(function (child) {
        if (child instanceof LineMorph) {
            child.stopStepping();
        };
    });
};

// LineMorph ///////////////////////////////////////////////////////////

// I am a line chart's line

// LineMorph inherits from Morph:


LineMorph.prototype = new Morph;
LineMorph.prototype.constructor = LineMorph;
LineMorph.uber = Morph.prototype;

// LineMorph instance creation:

function LineMorph(label, x, y, values, color, isFilled) {
	this.init(label, x, y, values, color, isFilled);
}

LineMorph.prototype.init = function (label, x, y, values, color, isFilled) {
	var rider;

	// additional attributes:
	this.label = label || '';
	this.xUnits = x || (x === 0 ? 0 : 5);
	this.yUnits = y || (y === 0 ? 0 : 200);
	this.values = values || [];
	this.isFilled = isFilled || false;

	this.lineWidth = 6;

	rider = new BoxMorph(this.lineWidth);
	this.add(rider);

	// initialize inherited attributes:
	LineMorph.uber.init.call(this);

	// override inherited attributes:
	this.color = color || new Color(255, 255, 255);
	this.setExtent(new Point(550, 280));
};

LineMorph.prototype.lineY = function (value) {
	var	yunit = this.height() / this.yUnits;
	return (this.height() - value * yunit) + this.top();
};

LineMorph.prototype.valueAt = function (x) {
	var	xunit = this.width() / this.xUnits,
		idx = Math.floor(x / xunit),
		left = idx * xunit,
		right = (idx + 1) * xunit;

	return this.values[idx] +
		((x - left) / (right - left)
			* (this.values[idx + 1] - this.values[idx]));
};

LineMorph.prototype.rider = function () {
	var rider, lbl;
	if (this.children[0]) {
		return this.children[0];
    }; lbl = new StringMorph(
        this.yUnits,
        10,
        null,
        false,
        false,
        false,
        new Point(-1, -1),
        this.color.darker(50)
    );
    lbl.setColor(new Color(255, 255, 255));

    rider = new BoxMorph(lbl.height() / 2);

    rider.border = 1;
    rider.setExtent(lbl.extent().add(rider.border + 4));
    rider.render = ChartMorph.prototype.renderGradient;
    rider.label = function () {return lbl;};

    rider.add(lbl);
    this.add(rider);
    return rider;
};

LineMorph.prototype.render = function (context) {
	// initialize my surface property

	context.strokeStyle = this.color.toString();
	context.lineWidth = this.lineWidth;
	context.lineJoin = 'round';

	context.beginPath();
	this.linePath(context);
	context.stroke();

	if (this.isFilled
	) {this.fill(context);
	}; var rider = this.rider();
	rider.borderColor = this.color.darker(40);
	rider.color = this.color.lighter(30);
	rider.rerender();
};

LineMorph.prototype.linePath = function (context) {
	var i, x, y;

	for (i = 0; i < this.values.length; i += 1) {
		if (!isNil(this.values[0])) {
			x = i * (this.width() / this.xUnits);
			y = this.height()
				- (this.values[i] * (this.height() / this.yUnits));
			if (i === 0) {
				context.moveTo(x, y);
			} else {
				context.lineTo(x, y);
			};
		};
	};
};

LineMorph.prototype.fill = function (context) {
	var halftone = this.color.copy();
	halftone.a = 1/5;

	context.fillStyle = halftone.toString();
	context.beginPath();
	this.linePath(context);
	context.lineTo(this.width(), this.height());
	context.lineTo(0, this.height());
	context.closePath();
	context.fill();
};

LineMorph.prototype.startStepping = function () {
	var myself = this; myself.rider().show();
	myself.step = function () {
		var pos = myself.world().hand.position(),
		value = this.valueAt(pos.x - this.left()),
		rider = this.rider();
		rider.label().setText(Math.round(value));
		rider.label().setCenter(rider.center());
		rider.setCenter(new Point(
			pos.x,
			myself.lineY(value)
		)); rider.show();
	};
};

LineMorph.prototype.stopStepping = function (
) {this.step = null; this.rider().hide();};

LineMorph.prototype.toggleFading = function () {
	if (this.isVisible) {
		this.hide();
	} else {
		this.show();
	}; this.rider().hide();
};

// ChartMorph //////////////////////////////////////////////////////////

// ChartMorph inherits from BoxMorph:

ChartMorph.prototype = new BoxMorph;
ChartMorph.prototype.constructor = ChartMorph;
ChartMorph.uber = BoxMorph.prototype;

// ChartMorph instance creation:

function ChartMorph() {this.init();};

ChartMorph.prototype.init = function () {
	this.label = 'Sales by Product';
	this.padding = 10;
	ChartMorph.uber.init.call(
	this, 0, 1, new Color(20, 20, 20)
	); this.color = new Color(50, 50, 50);
	this.edge = 10;
	this.contents = new GridMorph;
	this.labelMorph = null;
	this.zoomer = null;
	this.frame = null;
	this.legend = null;
	this.isDraggable = false;
	this.buildParts();
	this.setExtent(new Point(500, 400));
	this.handle = new HandleMorph(this, 275, 225, 4, 4);
	this.firstTime = false;
};

ChartMorph.prototype.buildParts = function () {
	var grid = this.contents, i, lm, last, myself = this;

	this.labelMorph = new StringMorph(
		this.label,
		grid.fontSize * 2,
		null,
		true,
		false
	);
	this.labelMorph.setColor(new Color(230, 230, 230));
	this.add(this.labelMorph);

	this.legend = new Morph;
	this.legend.color = new Color(80, 80, 80);
	this.add(this.legend);
	this.contents.children.forEach(function (c) {
		if (c instanceof LineMorph) {
			lm = new ToggleMorph(
				'checkbox',
				c,
				'toggleFading',
				c.label,
				(function anonymous () {return this.isVisible;}),
				null,
				null
			); lm.color = c.color;
			lm.highlightColor = c.color.lighter();
			lm.pressColor = c.color.darker();
			lm.rerender();
			lm.label.setColor(new Color(250, 250, 250));
			myself.legend.add(lm);
			if (last) {
				lm.setPosition(last.fullBounds().topRight().add(
					new Point(myself.padding, 0)
				));
			} else {
				lm.setPosition(
					myself.legend.position().add(myself.padding)
				);
			}; last = lm;
		};
	});

	this.frame = new ScrollFrameMorph(this.contents, 10);
	this.frame.alpha = 0;
	this.frame.isDraggable = false;
	this.frame.acceptsDrops = false;
	this.frame.scrollY = function () {};
	this.frame.mouseScroll = function (amount) {
		this.scrollX(amount * MorphicPreferences.mouseScrollAmount
                 ); this.adjustScrollBars();
	}; this.add(this.frame);

	this.zoomer = new SliderMorph;
	this.zoomer.orientation = 'vertical';
	this.zoomer.size = 10;
	this.zoomer.target = this;
	this.zoomer.action = this.zoom;
	this.add(this.zoomer);

	// create new y-axis labels:
	for (i = 0; i < grid.yUnits; i += grid.yInterval) {
		lm = new StringMorph(
			(i === 0 ? '0' : i.toString()),
			grid.fontSize,
			null,
			true,
			false
		); lm.isYLabel = true;
		lm.setColor(new Color(230, 230, 230));
		this.add(lm);
	};
};

// ChartMorph layout:

ChartMorph.prototype.fixLayout = function () {
	var grid = this.contents, inset, i, y, myself = this;

	if (this.labelMorph) {
		this.labelMorph.setCenter(this.center());
		this.labelMorph.setTop(this.top() + this.border + this.padding);
	}; if (this.legend) {
		this.legend.setExtent(new Point(
			this.width() - this.border,
			this.padding * 2 + 15
		));
		this.legend.setBottom(
			this.bottom() - this.border - this.edge - this.padding
		);
	}; if (this.frame) {
		inset = new StringMorph(
			grid.yUnits,
			grid.fontSize,
			null,
			false,
			false
		).width() + this.border + 3 + this.padding;
		this.frame.setPosition(new Point(
			this.left() + inset,
			this.labelMorph.bottom() + this.border + this.padding
		));
		this.frame.bounds.corner = this.legend.topRight().subtract(new Point(
			18 + this.padding,
			this.padding
		));
		this.frame.rerender();
		this.contents.setExtent(new Point(
			this.frame.width(),
			this.frame.height() - 30
		));
		this.frame.adjustScrollBars();

		// position y-axis labels:
		this.children.forEach(function (m) {
			if (m.isYLabel) {
				i = parseFloat(m.text);
				y = grid.height() - (i * (grid.height() / grid.yUnits))
					+ grid.top();
				m.setCenter(new Point(0, y));
				m.setRight(myself.frame.left() - 2);
			};
		});
	}; if (this.zoomer) {
		this.zoomer.setPosition(this.frame.topRight().add(
			new Point(5, 0)
		)); this.zoomer.bounds.corner = new Point(
			this.right() - this.border - this.padding,
			this.contents.bottom()
		); this.zoomer.start = this.frame.width();
		this.zoomer.stop = this.contents.xUnits / 3 * this.width();
		if (!(this.firstTime)) {this.firstTime = true;
                 this.zoomer.value = this.zoomer.start;};
                 this.zoomer.updateTarget();
		this.zoomer.size = (this.zoomer.stop - this.zoomer.start) / 5;
		this.zoomer.rerender();
		this.zoomer.changed();
	};
};

ChartMorph.prototype.zoom = function (w) {
	var xunit = this.contents.width() / this.contents.xUnits,
	offsetRatio = (this.frame.left() - this.contents.left()
	) / xunit; this.contents.setWidth(w);
	xunit = this.contents.width() / this.contents.xUnits;
	this.contents.setLeft(this.frame.left() - (xunit * offsetRatio));
	this.frame.scrollX(0);
	this.frame.adjustScrollBars();
};

// ChartMorph drawing:

ChartMorph.prototype.renderGradient = function (context) {
	var gradient;
	if ((this.edge === 0) && (this.border === 0)) {
		BoxMorph.uber.render.call(this, context);
		return;
	}; gradient = context.createLinearGradient(0, 0, 0, this.height());
	gradient.addColorStop(0, this.color.lighter(30).toString());
	gradient.addColorStop(1, this.color.darker(30).toString());
	context.fillStyle = gradient;
	context.beginPath();
	this.outlinePath(
		context,
		Math.max(this.edge - this.border, 0),
		this.border
	); context.closePath(); context.fill();
	if (this.border > 0) {
		gradient = context.createLinearGradient(0, 0, 0, this.height());
		gradient.addColorStop(0, this.borderColor.lighter(30).toString());
		gradient.addColorStop(1, this.borderColor.darker(30).toString());
		context.lineWidth = this.border;
		context.strokeStyle = gradient;
		context.beginPath();
		this.outlinePath(context, this.edge, this.border / 2);
		context.closePath();
		context.stroke();
	};
};

ChartMorph.prototype.render = function anonymous (
ctx) {this.renderGradient(ctx); this.fixLayout();};

I was asking so it can be hosted as a github page and to contribute

I'm creating the Super-Snap! Github page :wink:: https://github.com/Alessandrito123/Super-Snap

This is the current deployment of the Super-Snap! mod finally on GitHub!
If you want to commit it, please do it to improve it to take in the next versions.
https://alessandrito123.github.io/Super-Snap/

I played around with it for a bit, and it looks really good! Great job! The new blocks are very interesting. I'm still a little confused as to what the arrow blocks are supposed to represent. It is also pretty cool that you implemented first class colors in a way that works pretty well. The new inputs were also fun to play around with, as well as the new midi system.

I did also notice that you used my code for the cursor styles (with credit, or at least my name in the "Thanks to" dialog), which I think is cool.

I don't have time to create a demo project to see what it's really capable of, but still, great job. I know you've been working on it for years, and it's actually pretty high quality.

Thank you so much, my dear friend! I was preparing the Super-Snap! mod to be in GitHub finally and to be the more completed version for Super-Snap!, the development is endless! :~)

Wow I like it!

I love the Keemstar scream instrument :heart:

Wow, you got it so far. :clap: The Keemstar scream is a big sample for the midi located on joke.js and I perfectly put the note of the scream correctly, that fundamental note of the instrument is on 69.5. :wink:

Heh, nice and a half.