Commits

Anonymous committed b0cca8f

Scripting in Windows Port with Noesis v8 JavaScript engine

Comments (0)

Files changed (15)

Classes/JSWrappers.cpp

+//
+//  JSWrappers.mm
+//  MeshMaker
+//
+//  Created by Filip Kunc on 10/27/12.
+//
+//
+
+#include "JSWrappers.h"
+
+#if defined(__APPLE__)
+
+@implementation ItemCollectionWrapper
+
++ (NSString *)webScriptNameForSelector:(SEL)sel
+{
+    if (sel == @selector(at:))
+        return @"at";
+    return nil;
+}
+
++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector { return NO; }
++ (BOOL)isKeyExcludedFromWebScript:(const char *)name { return NO; }
+
+- (id)initWithItemCollection:(ItemCollection *)itemCollection
+{
+    self = [super init];
+    if (self)
+    {
+        _itemCollection = itemCollection;
+    }
+    return self;
+}
+
+- (uint)count
+{
+    return _itemCollection->count();
+}
+
+- (ItemWrapper *)at:(uint)index
+{
+    return [[ItemWrapper alloc] initWithItem:_itemCollection->itemAtIndex(index)];
+}
+
+@end
+
+@implementation ItemWrapper
+
+- (id)initWithItem:(Item *)item
+{
+    self = [super init];
+    if (self)
+    {
+        _item = item;
+    }
+    return self;
+}
+
+- (VertexNodeIterator *)vertexIterator
+{
+    return [[VertexNodeIterator alloc] initWithBegin:_item->mesh->vertices().begin() end:_item->mesh->vertices().end()];
+}
+
+- (TriangleNodeIterator *)triQuadIterator
+{
+    return [[TriangleNodeIterator alloc] initWithBegin:_item->mesh->triangles().begin() end:_item->mesh->triangles().end()];
+}
+
+- (EdgeNodeIterator *)edgeIterator
+{
+    return [[EdgeNodeIterator alloc] initWithBegin:_item->mesh->vertexEdges().begin() end:_item->mesh->vertexEdges().end()];
+}
+
+- (uint)vertexCount { return _item->mesh->vertexCount(); }
+- (uint)triQuadCount { return _item->mesh->triangleCount(); }
+- (BOOL)selected { return _item->selected; }
+- (void)setSelected:(BOOL)value { _item->selected = value; }
+
+- (void)removeDegeneratedTriangles { _item->mesh->removeDegeneratedTriangles(); }
+- (void)removeNonUsedVertices { _item->mesh->removeNonUsedVertices(); }
+- (void)removeNonUsedTexCoords { _item->mesh->removeNonUsedTexCoords(); }
+- (void)mergeSelected { _item->mesh->mergeSelected(); }
+- (void)splitSelected { _item->mesh->splitSelected(); }
+- (void)detachSelected { _item->mesh->detachSelected(); }
+- (void)duplicateSelectedTriangles { _item->mesh->duplicateSelectedTriangles(); }
+- (void)flipSelected { _item->mesh->flipSelected(); }
+- (void)flipAllTriangles { _item->mesh->flipAllTriangles(); }
+- (void)extrudeSelectedTriangles { _item->mesh->extrudeSelectedTriangles(); }
+- (void)triangulate { _item->mesh->triangulate(); }
+- (void)triangulateSelectedQuads { _item->mesh->triangulateSelectedQuads(); }
+- (void)openSubdivision { _item->mesh->openSubdivision(); }
+- (void)loopSubdivision { _item->mesh->loopSubdivision(); }
+- (void)makeTexCoords { _item->mesh->makeTexCoords(); }
+- (void)makeEdges { _item->mesh->makeEdges(); }
+- (void)updateSelection { _item->mesh->setSelectionMode(_item->mesh->selectionMode()); }
+- (void)setSelectionModeVertices { _item->mesh->setSelectionMode(MeshSelectionMode::Vertices); }
+- (void)setSelectionModeTriQuads { _item->mesh->setSelectionMode(MeshSelectionMode::Triangles); }
+- (void)setSelectionModeEdges { _item->mesh->setSelectionMode(MeshSelectionMode::Edges); }
+- (void)removeSelected { _item->removeSelected(); }
+
+- (VertexWrapper *)addVertexWithX:(float)x y:(float)y z:(float)z
+{
+    return [[VertexWrapper alloc] initWithNode:_item->mesh->addVertex(Vector3D(x, y, z))];
+}
+
+- (TriangleWrapper *)addTriangleWithFirst:(VertexWrapper *)v0 second:(VertexWrapper *)v1 third:(VertexWrapper *)v2
+{
+    return [[TriangleWrapper alloc] initWithNode:_item->mesh->addTriangle(v0.node, v1.node, v2.node)];
+}
+
+- (TriangleWrapper *)addQuadWithFirst:(VertexWrapper *)v0 second:(VertexWrapper *)v1 third:(VertexWrapper *)v2 fourth:(VertexWrapper *)v3
+{
+    return [[TriangleWrapper alloc] initWithNode:_item->mesh->addQuad(v0.node, v1.node, v2.node, v3.node)];
+}
+
+- (void)removeTriQuad:(TriangleWrapper *)triQuad
+{
+    TriangleNode *current = triQuad.node;
+    _item->mesh->removeTriQuad(current);
+    triQuad.node = current;
+}
+
++ (NSString *)webScriptNameForSelector:(SEL)sel
+{
+    if (sel == @selector(addVertexWithX:y:z:))
+        return @"addVertex";
+    if (sel == @selector(addTriangleWithFirst:second:third:))
+        return @"addTriangle";
+    if (sel == @selector(addQuadWithFirst:second:third:fourth:))
+        return @"addQuad";
+    if (sel == @selector(removeTriQuad:))
+        return @"removeTriQuad";
+    
+    return nil;
+}
+
++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector { return NO; }
++ (BOOL)isKeyExcludedFromWebScript:(const char *)name { return NO; }
+
+@end
+
+@implementation VertexWrapper
+
+@synthesize node;
+
+- (BOOL)selected { return node->data().selected; }
+- (void)setSelected:(BOOL)selected { node->data().selected = selected; }
+- (float)x { return node->data().position.x; }
+- (void)setX:(float)x { node->data().position.x = x; }
+- (float)y { return node->data().position.y; }
+- (void)setY:(float)y { node->data().position.y = y; }
+- (float)z { return node->data().position.z; }
+- (void)setZ:(float)z { node->data().position.z = z; }
+- (uint)index { return node->algorithmData.index; }
+- (void)setIndex:(uint)index { node->algorithmData.index = index; }
+- (uint)edgeCount { return node->_edges.count(); }
+- (VertexNodeEdgeIterator *)edgeIterator { return [[VertexNodeEdgeIterator alloc] initWithBegin:node->_edges.begin() end:node->_edges.end()]; }
+
+- (id)initWithNode:(VertexNode *)vertexNode
+{
+    self = [super init];
+    if (self)
+    {
+        node = vertexNode;
+    }
+    return self;
+}
+
++ (NSString *)webScriptNameForSelector:(SEL)sel
+{
+    if (sel == @selector(setSelected:))
+        return @"setSelected";
+    if (sel == @selector(setX:))
+        return @"setX";
+    if (sel == @selector(setY:))
+        return @"setY";
+    if (sel == @selector(setZ:))
+        return @"setZ";
+    if (sel == @selector(setIndex:))
+        return @"setIndex";
+    
+    return nil;
+}
+
++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector { return NO; }
++ (BOOL)isKeyExcludedFromWebScript:(const char *)name { return NO; }
+
+@end
+
+@implementation TriangleWrapper
+
+@synthesize node;
+
+- (BOOL)isQuad { return node->data().isQuad(); }
+- (uint)count { return node->data().count(); }
+- (BOOL)selected { return node->data().selected; }
+- (void)setSelected:(BOOL)selected { node->data().selected = selected; }
+
+- (id)initWithNode:(TriangleNode *)triangleNode
+{
+    self = [super init];
+    if (self)
+    {
+        node = triangleNode;
+    }
+    return self;
+}
+
+- (VertexWrapper *)vertexAtIndex:(uint)index
+{
+    return [[VertexWrapper alloc] initWithNode:node->data().vertex(index)];
+}
+
+- (void)setVertex:(VertexWrapper *)vertex atIndex:(uint)index
+{
+    node->data().setVertex(index, vertex.node);
+}
+
+- (EdgeWrapper *)edgeAtIndex:(uint)index
+{
+    return [[EdgeWrapper alloc] initWithNode:node->data().vertexEdge(index)];
+}
+
+- (void)setEdge:(EdgeWrapper *)edge atIndex:(uint)index
+{
+    node->data().setVertexEdge(index, edge.node);
+}
+
+- (VertexWrapper *)vertexNotInEdge:(EdgeWrapper *)edge
+{
+    return [[VertexWrapper alloc] initWithNode:node->data().vertexNotInEdge(&edge.node->data())];
+}
+
++ (NSString *)webScriptNameForSelector:(SEL)sel
+{
+    if (sel == @selector(setSelected:))
+        return @"setSelected";
+    if (sel == @selector(vertexAtIndex:))
+        return @"vertex";
+    if (sel == @selector(setVertex:atIndex:))
+        return @"setVertex";
+    if (sel == @selector(edgeAtIndex:))
+        return @"edge";
+    if (sel == @selector(setEdge:atIndex:))
+        return @"setEdge";
+    if (sel == @selector(vertexNotInEdge:))
+        return @"vertexNotInEdge";
+    
+    return nil;
+}
+
++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector { return NO; }
++ (BOOL)isKeyExcludedFromWebScript:(const char *)name { return NO; }
+
+@end
+
+@implementation EdgeWrapper
+
+@synthesize node;
+
+- (BOOL)selected { return node->data().selected; }
+- (void)setSelected:(BOOL)selected { node->data().selected = selected; }
+
+- (VertexWrapper *)half
+{
+    if (node->data().half)
+        return [[VertexWrapper alloc] initWithNode:node->data().half];
+    return nil;
+}
+
+- (void)setHalf:(VertexWrapper *)half
+{
+    if (half)
+        node->data().half = half.node;
+    else
+        node->data().half = NULL;
+}
+
+- (id)initWithNode:(VertexEdgeNode *)edgeNode
+{
+    self = [super init];
+    if (self)
+    {
+        node = edgeNode;
+    }
+    return self;
+}
+
+- (VertexWrapper *)vertexAtIndex:(uint)index
+{
+    VertexNode *vertex = node->data().vertex(index);
+    if (vertex)
+        return [[VertexWrapper alloc] initWithNode:vertex];
+    return nil;
+}
+
+- (void)setVertex:(VertexWrapper *)vertex atIndex:(uint)index
+{
+    if (vertex)
+        node->data().setVertex(index, vertex.node);
+    else
+        node->data().setVertex(index, NULL);
+}
+
+- (TriangleWrapper *)triangleAtIndex:(uint)index
+{
+    TriangleNode *triangle = node->data().triangle(index);
+    if (triangle)
+        return [[TriangleWrapper alloc] initWithNode:triangle];
+    return nil;
+}
+
+- (void)setTriangle:(TriangleWrapper *)triangle atIndex:(uint)index
+{
+    if (triangle)
+        node->data().setTriangle(index, triangle.node);
+    else
+        node->data().setTriangle(index, NULL);
+}
+
+- (VertexWrapper *)oppositeVertex:(VertexWrapper *)vertex
+{
+    return [[VertexWrapper alloc] initWithNode:node->data().opposite(vertex.node)];
+}
+
++ (NSString *)webScriptNameForSelector:(SEL)sel
+{
+    if (sel == @selector(setSelected:))
+        return @"setSelected";
+    if (sel == @selector(vertexAtIndex:))
+        return @"vertex";
+    if (sel == @selector(setVertex:atIndex:))
+        return @"setVertex";
+    if (sel == @selector(triangleAtIndex:))
+        return @"triangle";
+    if (sel == @selector(setTriangle:atIndex:))
+        return @"setTriangle";
+    if (sel == @selector(setHalf:))
+        return @"setHalf";
+    if (sel == @selector(oppositeVertex:))
+        return @"oppositeVertex";
+    
+    return nil;
+}
+
++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector { return NO; }
++ (BOOL)isKeyExcludedFromWebScript:(const char *)name { return NO; }
+
+@end
+
+@implementation VertexNodeEdgeWrapper
+
+- (Vertex2VEdgeNode *)simpleNode
+{
+    return _simpleNode;
+}
+
+- (void)setSimpleNode:(Vertex2VEdgeNode *)simpleNode
+{
+    _simpleNode = simpleNode;
+    self.node = _simpleNode->data();
+}
+
+- (id)initWithSimpleNode:(Vertex2VEdgeNode *)edgeNode
+{
+    self = [self initWithNode:edgeNode->data()];
+    if (self)
+    {
+        _simpleNode = edgeNode;
+    }
+    return self;
+}
+
+@end
+
+#define ImplementIterator(Name, TNode, nodeProperty) \
+@implementation Name \
+\
+- (BOOL)finished { return self.nodeProperty == end; } \
+\
+- (id)initWithBegin:(TNode *)theBegin end:(TNode *)theEnd \
+{ \
+    self = [super init]; \
+    if (self) \
+    { \
+        begin = theBegin; \
+        end = theEnd; \
+        self.nodeProperty = begin; \
+    } \
+    return self; \
+} \
+\
+- (void)moveStart { self.nodeProperty = begin; } \
+- (void)moveNext { self.nodeProperty = self.nodeProperty->next(); } \
+\
++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector \
+{ \
+    return NO; \
+} \
++ (BOOL)isKeyExcludedFromWebScript:(const char *)name { return NO; } \
+\
+@end
+
+ImplementIterator(VertexNodeIterator, VertexNode, node)
+ImplementIterator(TriangleNodeIterator, TriangleNode, node)
+ImplementIterator(EdgeNodeIterator, VertexEdgeNode, node)
+ImplementIterator(VertexNodeEdgeIterator, Vertex2VEdgeNode, simpleNode)
+
+#elif defined(WIN32)
+
+namespace MeshMakerCppCLI
+{
+
+ItemCollectionWrapper::ItemCollectionWrapper(ItemCollection *itemCollection)
+{
+	_itemCollection = itemCollection;
+}
+
+int ItemCollectionWrapper::count()
+{
+    return _itemCollection->count();
+}
+
+ItemWrapper ^ItemCollectionWrapper::at(int index)
+{
+	return gcnew ItemWrapper(_itemCollection->itemAtIndex(index));
+}
+
+ItemWrapper::ItemWrapper(Item *item)
+{
+	_item = item;
+}
+
+VertexNodeIterator ^ItemWrapper::vertexIterator()
+{
+	return gcnew VertexNodeIterator(_item->mesh->vertices().begin(), _item->mesh->vertices().end());
+}
+
+TriangleNodeIterator ^ItemWrapper::triQuadIterator()
+{
+	return gcnew TriangleNodeIterator(_item->mesh->triangles().begin(), _item->mesh->triangles().end());
+}
+
+EdgeNodeIterator ^ItemWrapper::edgeIterator()
+{
+	return gcnew EdgeNodeIterator(_item->mesh->vertexEdges().begin(), _item->mesh->vertexEdges().end());
+}
+
+int ItemWrapper::vertexCount() { return _item->mesh->vertexCount(); }
+int ItemWrapper::triQuadCount() { return _item->mesh->triangleCount(); }
+bool ItemWrapper::selected() { return _item->selected; }
+void ItemWrapper::setSelected(bool selected) { _item->selected = selected; }
+
+void ItemWrapper::removeDegeneratedTriangles() { _item->mesh->removeDegeneratedTriangles(); }
+void ItemWrapper::removeNonUsedVertices() { _item->mesh->removeNonUsedVertices(); }
+void ItemWrapper::removeNonUsedTexCoords() { _item->mesh->removeNonUsedTexCoords(); }
+void ItemWrapper::mergeSelected() { _item->mesh->mergeSelected(); }
+void ItemWrapper::splitSelected() { _item->mesh->splitSelected(); }
+void ItemWrapper::detachSelected() { _item->mesh->detachSelected(); }
+void ItemWrapper::duplicateSelectedTriangles() { _item->mesh->duplicateSelectedTriangles(); }
+void ItemWrapper::flipSelected() { _item->mesh->flipSelected(); }
+void ItemWrapper::flipAllTriangles() { _item->mesh->flipAllTriangles(); }
+void ItemWrapper::extrudeSelectedTriangles() { _item->mesh->extrudeSelectedTriangles(); }
+void ItemWrapper::triangulate() { _item->mesh->triangulate(); }
+void ItemWrapper::triangulateSelectedQuads() { _item->mesh->triangulateSelectedQuads(); }
+void ItemWrapper::openSubdivision() { _item->mesh->openSubdivision(); }
+void ItemWrapper::loopSubdivision() { _item->mesh->loopSubdivision(); }
+void ItemWrapper::makeTexCoords() { _item->mesh->makeTexCoords(); }
+void ItemWrapper::makeEdges() { _item->mesh->makeEdges(); }
+void ItemWrapper::updateSelection() { _item->mesh->setSelectionMode(_item->mesh->selectionMode()); }
+void ItemWrapper::setSelectionModeVertices() { _item->mesh->setSelectionMode(MeshSelectionMode::Vertices); }
+void ItemWrapper::setSelectionModeTriQuads() { _item->mesh->setSelectionMode(MeshSelectionMode::Triangles); }
+void ItemWrapper::setSelectionModeEdges() { _item->mesh->setSelectionMode(MeshSelectionMode::Edges); }
+void ItemWrapper::removeSelected() { _item->removeSelected(); }
+
+VertexWrapper ^ItemWrapper::addVertex(float x, float y, float z)
+{
+	return gcnew VertexWrapper(_item->mesh->addVertex(Vector3D(x, y, z)));
+}
+
+TriangleWrapper ^ItemWrapper::addTriangle(VertexWrapper ^v0, VertexWrapper ^v1, VertexWrapper ^v2)
+{
+	return gcnew TriangleWrapper(_item->mesh->addTriangle(v0->node(), v1->node(), v2->node()));
+}
+
+TriangleWrapper ^ItemWrapper::addQuad(VertexWrapper ^v0, VertexWrapper ^v1, VertexWrapper ^v2, VertexWrapper ^v3)
+{
+	return gcnew TriangleWrapper(_item->mesh->addQuad(v0->node(), v1->node(), v2->node(), v3->node()));
+}
+
+void ItemWrapper::removeTriQuad(TriangleWrapper ^triQuad)
+{
+    TriangleNode *current = triQuad->node();
+    _item->mesh->removeTriQuad(current);
+	triQuad->setNode(current);
+}
+
+VertexWrapper::VertexWrapper(VertexNode *node)
+{
+	_node = node;
+}
+
+VertexNode *VertexWrapper::node() {	return _node; }
+void VertexWrapper::setNode(VertexNode *value) { _node = value; }
+bool VertexWrapper::selected() { return _node->data().selected; }
+void VertexWrapper::setSelected(bool selected) { _node->data().selected = selected; }
+float VertexWrapper::x() { return _node->data().position.x; }
+void VertexWrapper::setX(float x) { _node->data().position.x = x; }
+float VertexWrapper::y() { return _node->data().position.y; }
+void VertexWrapper::setY(float y) { _node->data().position.y = y; }
+float VertexWrapper::z() { return _node->data().position.z; }
+void VertexWrapper::setZ(float z) { _node->data().position.z = z; }
+int VertexWrapper::index() { return _node->algorithmData.index; }
+void VertexWrapper::setIndex(int index) { _node->algorithmData.index = index; }
+int VertexWrapper::edgeCount() { return _node->_edges.count(); }
+VertexNodeEdgeIterator ^VertexWrapper::edgeIterator() { return gcnew VertexNodeEdgeIterator(_node->_edges.begin(), _node->_edges.end()); }
+
+TriangleWrapper::TriangleWrapper(TriangleNode *node)
+{
+	_node = node;
+}
+
+TriangleNode *TriangleWrapper::node() { return _node; }
+void TriangleWrapper::setNode(TriangleNode *node) { _node = node; }
+bool TriangleWrapper::isQuad() { return _node->data().isQuad(); }
+int TriangleWrapper::count() { return _node->data().count(); }
+bool TriangleWrapper::selected() { return _node->data().selected; }
+void TriangleWrapper::setSelected(bool selected) { _node->data().selected = selected; }
+
+VertexWrapper ^TriangleWrapper::vertex(int index)
+{
+	return gcnew VertexWrapper(_node->data().vertex(index));
+}
+
+void TriangleWrapper::setVertex(VertexWrapper ^vertex, int index)
+{
+	_node->data().setVertex(index, vertex->node());
+}
+
+EdgeWrapper ^TriangleWrapper::edge(int index)
+{
+	return gcnew EdgeWrapper(_node->data().vertexEdge(index));
+}
+
+void TriangleWrapper::setEdge(EdgeWrapper ^edge, int index)
+{
+	_node->data().setVertexEdge(index, edge->node());
+}
+
+VertexWrapper ^TriangleWrapper::vertexNotInEdge(EdgeWrapper ^edge)
+{
+	return gcnew VertexWrapper(_node->data().vertexNotInEdge(&edge->node()->data()));
+}
+
+EdgeWrapper::EdgeWrapper(VertexEdgeNode *node)
+{
+	_node = node;
+}
+
+VertexEdgeNode *EdgeWrapper::node() { return _node; }
+void EdgeWrapper::setNode(VertexEdgeNode *node) { _node = node; }
+bool EdgeWrapper::selected() { return _node->data().selected; }
+void EdgeWrapper::setSelected(bool selected) { _node->data().selected = selected; }
+
+VertexWrapper ^EdgeWrapper::half()
+{
+	if (_node->data().half)
+        return gcnew VertexWrapper(_node->data().half);
+    return nullptr;
+}
+
+void EdgeWrapper::setHalf(VertexWrapper ^half)
+{
+    if (half)
+        _node->data().half = half->node();
+    else
+        _node->data().half = NULL;
+}
+
+VertexWrapper ^EdgeWrapper::vertex(int index)
+{
+    VertexNode *vertex = _node->data().vertex(index);
+    if (vertex)
+        return gcnew VertexWrapper(vertex);
+    return nullptr;
+}
+
+void EdgeWrapper::setVertex(VertexWrapper ^vertex, int index)
+{
+    if (vertex)
+        _node->data().setVertex(index, vertex->node());
+    else
+        _node->data().setVertex(index, NULL);
+}
+
+TriangleWrapper ^EdgeWrapper::triangle(int index)
+{
+    TriangleNode *triangle = _node->data().triangle(index);
+    if (triangle)
+        return gcnew TriangleWrapper(triangle);
+    return nullptr;
+}
+
+void EdgeWrapper::setTriangle(TriangleWrapper ^triangle, int index)
+{
+    if (triangle)
+        _node->data().setTriangle(index, triangle->node());
+    else
+        _node->data().setTriangle(index, NULL);
+}
+
+VertexWrapper ^EdgeWrapper::oppositeVertex(VertexWrapper ^vertex)
+{
+	return gcnew VertexWrapper(_node->data().opposite(vertex->node()));
+}
+
+VertexNodeEdgeWrapper::VertexNodeEdgeWrapper(Vertex2VEdgeNode *edgeNode)
+	: EdgeWrapper(edgeNode->data())
+{
+	_simpleNode = edgeNode;
+}
+
+Vertex2VEdgeNode *VertexNodeEdgeWrapper::simpleNode()
+{
+	return _simpleNode;
+}
+
+void VertexNodeEdgeWrapper::setSimpleNode(Vertex2VEdgeNode *simpleNode)
+{
+    _simpleNode = simpleNode;
+    setNode(_simpleNode->data());
+}
+
+#define ImplementIterator(Name, TBase, TNode, nodeProperty, setNodeProperty) \
+\
+Name::Name(TNode *theBegin, TNode *theEnd) \
+	: TBase(theBegin) \
+{ \
+	begin = theBegin; \
+	end = theEnd; \
+} \
+\
+bool Name::finished() { return this->nodeProperty() == end; } \
+void Name::moveStart() { this->setNodeProperty(begin); } \
+void Name::moveNext() { this->setNodeProperty(this->nodeProperty()->next()); }
+
+ImplementIterator(VertexNodeIterator, VertexWrapper, VertexNode, node, setNode)
+ImplementIterator(TriangleNodeIterator, TriangleWrapper, TriangleNode, node, setNode)
+ImplementIterator(EdgeNodeIterator, EdgeWrapper, VertexEdgeNode, node, setNode)
+ImplementIterator(VertexNodeEdgeIterator, VertexNodeEdgeWrapper, Vertex2VEdgeNode, simpleNode, setSimpleNode)
+
+}
+
+#endif

Classes/JSWrappers.h

 
 #pragma once
 
-#import "ItemCollection.h"
+#include "ItemCollection.h"
+
+#if defined (__APPLE__)
 
 @class VertexWrapper;
 @class TriangleWrapper;
 @class VertexNodeIterator;
 @class TriangleNodeIterator;
 @class EdgeNodeIterator;
-@class SimpleNodeEdgeIterator;
+@class VertexNodeEdgeIterator;
 @class ItemWrapper;
 
 @interface ItemCollectionWrapper : NSObject
 @property (readwrite, assign) float z;
 @property (readwrite, assign) uint index;
 @property (readonly) uint edgeCount;
-@property (readonly) SimpleNodeEdgeIterator *edgeIterator;
+@property (readonly) VertexNodeEdgeIterator *edgeIterator;
 
 - (id)initWithNode:(VertexNode *)vertexNode;
 
 DeclareIterator(TriangleNodeIterator, TriangleWrapper, TriangleNode)
 DeclareIterator(EdgeNodeIterator, EdgeWrapper, VertexEdgeNode)
 DeclareIterator(VertexNodeEdgeIterator, VertexNodeEdgeWrapper, Vertex2VEdgeNode)
+
+#elif defined(WIN32)
+
+namespace MeshMakerCppCLI
+{
+
+using namespace System;
+using namespace System::Runtime::InteropServices;
+
+ref class VertexWrapper;
+ref class TriangleWrapper;
+ref class EdgeWrapper;
+ref class SimpleNodeEdgeWrapper;
+ref class VertexNodeIterator;
+ref class TriangleNodeIterator;
+ref class EdgeNodeIterator;
+ref class VertexNodeEdgeIterator;
+ref class ItemWrapper;
+
+[ComVisibleAttribute(true)]
+public ref class ItemCollectionWrapper
+{
+private:
+    ItemCollection *_itemCollection;
+public:
+	ItemCollectionWrapper(ItemCollection *itemCollection);
+	int count();
+	ItemWrapper ^at(int index);
+};
+
+[ComVisibleAttribute(true)]
+public ref class ItemWrapper
+{
+private:
+    Item *_item;
+public:
+	ItemWrapper(Item *item);
+	VertexNodeIterator ^vertexIterator();
+	TriangleNodeIterator ^triQuadIterator();
+	EdgeNodeIterator ^edgeIterator();
+
+	int vertexCount();
+	int triQuadCount();
+	bool selected();
+	void setSelected(bool selected);
+
+	VertexWrapper ^addVertex(float x, float y, float z);
+	TriangleWrapper ^addTriangle(VertexWrapper ^v0, VertexWrapper ^v1, VertexWrapper ^v2);
+	TriangleWrapper ^addQuad(VertexWrapper ^v0, VertexWrapper ^v1, VertexWrapper ^v2, VertexWrapper ^v3);
+	void removeTriQuad(TriangleWrapper ^triQuad);
+
+	void removeDegeneratedTriangles();
+	void removeNonUsedVertices();
+	void removeNonUsedTexCoords();
+	void mergeSelected();
+	void splitSelected();
+	void detachSelected();
+	void duplicateSelectedTriangles();
+	void flipSelected();
+	void flipAllTriangles();
+	void extrudeSelectedTriangles();
+	void triangulate();
+	void triangulateSelectedQuads();
+	void openSubdivision();
+	void loopSubdivision();
+	void makeTexCoords();
+	void makeEdges();
+	void updateSelection();
+	void setSelectionModeVertices();
+	void setSelectionModeTriQuads();
+	void setSelectionModeEdges();
+	void removeSelected();
+};
+
+[ComVisibleAttribute(true)]
+public ref class VertexWrapper
+{
+private:
+	VertexNode *_node;
+public:
+	VertexWrapper(VertexNode *node);
+
+	VertexNode *node();
+	void setNode(VertexNode *node);
+
+	bool selected();
+	void setSelected(bool selected);
+
+	float x();
+	void setX(float x);
+
+	float y();
+	void setY(float y);
+
+	float z();
+	void setZ(float z);
+
+	int index();
+	void setIndex(int index);
+
+	int edgeCount();
+	VertexNodeEdgeIterator ^edgeIterator();
+};
+
+[ComVisibleAttribute(true)]
+public ref class TriangleWrapper
+{
+private:
+	TriangleNode *_node;
+public:
+	TriangleWrapper(TriangleNode *node);
+
+	TriangleNode *node();
+	void setNode(TriangleNode *node);
+
+	bool selected();
+	void setSelected(bool selected);
+
+	bool isQuad();
+	int count();
+
+	VertexWrapper ^vertex(int index);
+	void setVertex(VertexWrapper ^vertex, int index);
+
+	EdgeWrapper ^edge(int index);
+	void setEdge(EdgeWrapper ^edge, int index);
+
+	VertexWrapper ^vertexNotInEdge(EdgeWrapper ^edge);
+};
+
+[ComVisibleAttribute(true)]
+public ref class EdgeWrapper
+{
+private:
+	VertexEdgeNode *_node;
+public:
+	EdgeWrapper(VertexEdgeNode *node);
+
+	VertexEdgeNode *node();
+	void setNode(VertexEdgeNode *node);
+
+	bool selected();
+	void setSelected(bool selected);
+
+	VertexWrapper ^half();
+	void setHalf(VertexWrapper ^half);
+
+	VertexWrapper ^vertex(int index);
+	void setVertex(VertexWrapper ^vertex, int index);
+
+	TriangleWrapper ^triangle(int index);
+	void setTriangle(TriangleWrapper ^triangle, int index);
+
+	VertexWrapper ^oppositeVertex(VertexWrapper ^vertex);
+};
+
+[ComVisibleAttribute(true)]
+public ref class VertexNodeEdgeWrapper : public EdgeWrapper
+{
+private:
+    Vertex2VEdgeNode *_simpleNode;
+public:
+	VertexNodeEdgeWrapper(Vertex2VEdgeNode *edgeNode);
+
+	Vertex2VEdgeNode *simpleNode();
+	void setSimpleNode(Vertex2VEdgeNode *simpleNode);
+};
+
+#define DeclareIterator(Name, TBase, TNode) \
+[ComVisibleAttribute(true)] \
+public ref class Name : public TBase \
+{ \
+private: \
+    TNode *begin; \
+    TNode *end; \
+public: \
+	Name(TNode *theBegin, TNode *theEnd); \
+	bool finished(); \
+	void moveStart(); \
+	void moveNext(); \
+};
+
+DeclareIterator(VertexNodeIterator, VertexWrapper, VertexNode)
+DeclareIterator(TriangleNodeIterator, TriangleWrapper, TriangleNode)
+DeclareIterator(EdgeNodeIterator, EdgeWrapper, VertexEdgeNode)
+DeclareIterator(VertexNodeEdgeIterator, VertexNodeEdgeWrapper, Vertex2VEdgeNode)
+
+}
+
+#endif

Classes/JSWrappers.mm

-//
-//  JSWrappers.mm
-//  MeshMaker
-//
-//  Created by Filip Kunc on 10/27/12.
-//
-//
-
-#import "JSWrappers.h"
-
-@implementation ItemCollectionWrapper
-
-+ (NSString *)webScriptNameForSelector:(SEL)sel
-{
-    if (sel == @selector(at:))
-        return @"at";
-    return nil;
-}
-
-+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector { return NO; }
-+ (BOOL)isKeyExcludedFromWebScript:(const char *)name { return NO; }
-
-- (id)initWithItemCollection:(ItemCollection *)itemCollection
-{
-    self = [super init];
-    if (self)
-    {
-        _itemCollection = itemCollection;
-    }
-    return self;
-}
-
-- (uint)count
-{
-    return _itemCollection->count();
-}
-
-- (ItemWrapper *)at:(uint)index
-{
-    return [[ItemWrapper alloc] initWithItem:_itemCollection->itemAtIndex(index)];
-}
-
-@end
-
-@implementation ItemWrapper
-
-- (id)initWithItem:(Item *)item
-{
-    self = [super init];
-    if (self)
-    {
-        _item = item;
-    }
-    return self;
-}
-
-- (VertexNodeIterator *)vertexIterator
-{
-    return [[VertexNodeIterator alloc] initWithBegin:_item->mesh->vertices().begin() end:_item->mesh->vertices().end()];
-}
-
-- (TriangleNodeIterator *)triQuadIterator
-{
-    return [[TriangleNodeIterator alloc] initWithBegin:_item->mesh->triangles().begin() end:_item->mesh->triangles().end()];
-}
-
-- (EdgeNodeIterator *)edgeIterator
-{
-    return [[EdgeNodeIterator alloc] initWithBegin:_item->mesh->vertexEdges().begin() end:_item->mesh->vertexEdges().end()];
-}
-
-- (uint)vertexCount { return _item->mesh->vertexCount(); }
-- (uint)triQuadCount { return _item->mesh->triangleCount(); }
-- (BOOL)selected { return _item->selected; }
-- (void)setSelected:(BOOL)value { _item->selected = value; }
-
-- (void)removeDegeneratedTriangles { _item->mesh->removeDegeneratedTriangles(); }
-- (void)removeNonUsedVertices { _item->mesh->removeNonUsedVertices(); }
-- (void)removeNonUsedTexCoords { _item->mesh->removeNonUsedTexCoords(); }
-- (void)mergeSelected { _item->mesh->mergeSelected(); }
-- (void)splitSelected { _item->mesh->splitSelected(); }
-- (void)detachSelected { _item->mesh->detachSelected(); }
-- (void)duplicateSelectedTriangles { _item->mesh->duplicateSelectedTriangles(); }
-- (void)flipSelected { _item->mesh->flipSelected(); }
-- (void)flipAllTriangles { _item->mesh->flipAllTriangles(); }
-- (void)extrudeSelectedTriangles { _item->mesh->extrudeSelectedTriangles(); }
-- (void)triangulate { _item->mesh->triangulate(); }
-- (void)triangulateSelectedQuads { _item->mesh->triangulateSelectedQuads(); }
-- (void)openSubdivision { _item->mesh->openSubdivision(); }
-- (void)loopSubdivision { _item->mesh->loopSubdivision(); }
-- (void)makeTexCoords { _item->mesh->makeTexCoords(); }
-- (void)makeEdges { _item->mesh->makeEdges(); }
-- (void)updateSelection { _item->mesh->setSelectionMode(_item->mesh->selectionMode()); }
-- (void)setSelectionModeVertices { _item->mesh->setSelectionMode(MeshSelectionMode::Vertices); }
-- (void)setSelectionModeTriQuads { _item->mesh->setSelectionMode(MeshSelectionMode::Triangles); }
-- (void)setSelectionModeEdges { _item->mesh->setSelectionMode(MeshSelectionMode::Edges); }
-- (void)removeSelected { _item->removeSelected(); }
-
-- (VertexWrapper *)addVertexWithX:(float)x y:(float)y z:(float)z
-{
-    return [[VertexWrapper alloc] initWithNode:_item->mesh->addVertex(Vector3D(x, y, z))];
-}
-
-- (TriangleWrapper *)addTriangleWithFirst:(VertexWrapper *)v0 second:(VertexWrapper *)v1 third:(VertexWrapper *)v2
-{
-    return [[TriangleWrapper alloc] initWithNode:_item->mesh->addTriangle(v0.node, v1.node, v2.node)];
-}
-
-- (TriangleWrapper *)addQuadWithFirst:(VertexWrapper *)v0 second:(VertexWrapper *)v1 third:(VertexWrapper *)v2 fourth:(VertexWrapper *)v3
-{
-    return [[TriangleWrapper alloc] initWithNode:_item->mesh->addQuad(v0.node, v1.node, v2.node, v3.node)];
-}
-
-- (void)removeTriQuad:(TriangleWrapper *)triQuad
-{
-    TriangleNode *current = triQuad.node;
-    _item->mesh->removeTriQuad(current);
-    triQuad.node = current;
-}
-
-+ (NSString *)webScriptNameForSelector:(SEL)sel
-{
-    if (sel == @selector(addVertexWithX:y:z:))
-        return @"addVertex";
-    if (sel == @selector(addTriangleWithFirst:second:third:))
-        return @"addTriangle";
-    if (sel == @selector(addQuadWithFirst:second:third:fourth:))
-        return @"addQuad";
-    if (sel == @selector(removeTriQuad:))
-        return @"removeTriQuad";
-    
-    return nil;
-}
-
-+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector { return NO; }
-+ (BOOL)isKeyExcludedFromWebScript:(const char *)name { return NO; }
-
-@end
-
-@implementation VertexWrapper
-
-@synthesize node;
-
-- (BOOL)selected { return node->data().selected; }
-- (void)setSelected:(BOOL)selected { node->data().selected = selected; }
-- (float)x { return node->data().position.x; }
-- (void)setX:(float)x { node->data().position.x = x; }
-- (float)y { return node->data().position.y; }
-- (void)setY:(float)y { node->data().position.y = y; }
-- (float)z { return node->data().position.z; }
-- (void)setZ:(float)z { node->data().position.z = z; }
-- (uint)index { return node->algorithmData.index; }
-- (void)setIndex:(uint)index { node->algorithmData.index = index; }
-- (uint)edgeCount { return node->_edges.count(); }
-- (VertexNodeEdgeIterator *)edgeIterator { return [[VertexNodeEdgeIterator alloc] initWithBegin:node->_edges.begin() end:node->_edges.end()]; }
-
-- (id)initWithNode:(VertexNode *)vertexNode
-{
-    self = [super init];
-    if (self)
-    {
-        node = vertexNode;
-    }
-    return self;
-}
-
-+ (NSString *)webScriptNameForSelector:(SEL)sel
-{
-    if (sel == @selector(setSelected:))
-        return @"setSelected";
-    if (sel == @selector(setX:))
-        return @"setX";
-    if (sel == @selector(setY:))
-        return @"setY";
-    if (sel == @selector(setZ:))
-        return @"setZ";
-    if (sel == @selector(setIndex:))
-        return @"setIndex";
-    
-    return nil;
-}
-
-+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector { return NO; }
-+ (BOOL)isKeyExcludedFromWebScript:(const char *)name { return NO; }
-
-@end
-
-@implementation TriangleWrapper
-
-@synthesize node;
-
-- (BOOL)isQuad { return node->data().isQuad(); }
-- (uint)count { return node->data().count(); }
-- (BOOL)selected { return node->data().selected; }
-- (void)setSelected:(BOOL)selected { node->data().selected = selected; }
-
-- (id)initWithNode:(TriangleNode *)triangleNode
-{
-    self = [super init];
-    if (self)
-    {
-        node = triangleNode;
-    }
-    return self;
-}
-
-- (VertexWrapper *)vertexAtIndex:(uint)index
-{
-    return [[VertexWrapper alloc] initWithNode:node->data().vertex(index)];
-}
-
-- (void)setVertex:(VertexWrapper *)vertex atIndex:(uint)index
-{
-    node->data().setVertex(index, vertex.node);
-}
-
-- (EdgeWrapper *)edgeAtIndex:(uint)index
-{
-    return [[EdgeWrapper alloc] initWithNode:node->data().vertexEdge(index)];
-}
-
-- (void)setEdge:(EdgeWrapper *)edge atIndex:(uint)index
-{
-    node->data().setVertexEdge(index, edge.node);
-}
-
-- (VertexWrapper *)vertexNotInEdge:(EdgeWrapper *)edge
-{
-    return [[VertexWrapper alloc] initWithNode:node->data().vertexNotInEdge(&edge.node->data())];
-}
-
-+ (NSString *)webScriptNameForSelector:(SEL)sel
-{
-    if (sel == @selector(setSelected:))
-        return @"setSelected";
-    if (sel == @selector(vertexAtIndex:))
-        return @"vertex";
-    if (sel == @selector(setVertex:atIndex:))
-        return @"setVertex";
-    if (sel == @selector(edgeAtIndex:))
-        return @"edge";
-    if (sel == @selector(setEdge:atIndex:))
-        return @"setEdge";
-    if (sel == @selector(vertexNotInEdge:))
-        return @"vertexNotInEdge";
-    
-    return nil;
-}
-
-+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector { return NO; }
-+ (BOOL)isKeyExcludedFromWebScript:(const char *)name { return NO; }
-
-@end
-
-@implementation EdgeWrapper
-
-@synthesize node;
-
-- (BOOL)selected { return node->data().selected; }
-- (void)setSelected:(BOOL)selected { node->data().selected = selected; }
-
-- (VertexWrapper *)half
-{
-    if (node->data().half)
-        return [[VertexWrapper alloc] initWithNode:node->data().half];
-    return nil;
-}
-
-- (void)setHalf:(VertexWrapper *)half
-{
-    if (half)
-        node->data().half = half.node;
-    else
-        node->data().half = NULL;
-}
-
-- (id)initWithNode:(VertexEdgeNode *)edgeNode
-{
-    self = [super init];
-    if (self)
-    {
-        node = edgeNode;
-    }
-    return self;
-}
-
-- (VertexWrapper *)vertexAtIndex:(uint)index
-{
-    VertexNode *vertex = node->data().vertex(index);
-    if (vertex)
-        return [[VertexWrapper alloc] initWithNode:vertex];
-    return nil;
-}
-
-- (void)setVertex:(VertexWrapper *)vertex atIndex:(uint)index
-{
-    if (vertex)
-        node->data().setVertex(index, vertex.node);
-    else
-        node->data().setVertex(index, NULL);
-}
-
-- (TriangleWrapper *)triangleAtIndex:(uint)index
-{
-    TriangleNode *triangle = node->data().triangle(index);
-    if (triangle)
-        return [[TriangleWrapper alloc] initWithNode:triangle];
-    return nil;
-}
-
-- (void)setTriangle:(TriangleWrapper *)triangle atIndex:(uint)index
-{
-    if (triangle)
-        node->data().setTriangle(index, triangle.node);
-    else
-        node->data().setTriangle(index, NULL);
-}
-
-- (VertexWrapper *)oppositeVertex:(VertexWrapper *)vertex
-{
-    return [[VertexWrapper alloc] initWithNode:node->data().opposite(vertex.node)];
-}
-
-+ (NSString *)webScriptNameForSelector:(SEL)sel
-{
-    if (sel == @selector(setSelected:))
-        return @"setSelected";
-    if (sel == @selector(vertexAtIndex:))
-        return @"vertex";
-    if (sel == @selector(setVertex:atIndex:))
-        return @"setVertex";
-    if (sel == @selector(triangleAtIndex:))
-        return @"triangle";
-    if (sel == @selector(setTriangle:atIndex:))
-        return @"setTriangle";
-    if (sel == @selector(setHalf:))
-        return @"setHalf";
-    if (sel == @selector(oppositeVertex:))
-        return @"oppositeVertex";
-    
-    return nil;
-}
-
-+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector { return NO; }
-+ (BOOL)isKeyExcludedFromWebScript:(const char *)name { return NO; }
-
-@end
-
-@implementation VertexNodeEdgeWrapper
-
-- (Vertex2VEdgeNode *)simpleNode
-{
-    return _simpleNode;
-}
-
-- (void)setSimpleNode:(Vertex2VEdgeNode *)simpleNode
-{
-    _simpleNode = simpleNode;
-    self.node = _simpleNode->data();
-}
-
-- (id)initWithSimpleNode:(Vertex2VEdgeNode *)edgeNode
-{
-    self = [self initWithNode:edgeNode->data()];
-    if (self)
-    {
-        _simpleNode = edgeNode;
-    }
-    return self;
-}
-
-@end
-
-#define ImplementIterator(Name, TNode, nodeProperty) \
-@implementation Name \
-\
-- (BOOL)finished { return self.nodeProperty == end; } \
-\
-- (id)initWithBegin:(TNode *)theBegin end:(TNode *)theEnd \
-{ \
-    self = [super init]; \
-    if (self) \
-    { \
-        begin = theBegin; \
-        end = theEnd; \
-        self.nodeProperty = begin; \
-    } \
-    return self; \
-} \
-\
-- (void)moveStart { self.nodeProperty = begin; } \
-- (void)moveNext { self.nodeProperty = self.nodeProperty->next(); } \
-\
-+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector \
-{ \
-    return NO; \
-} \
-+ (BOOL)isKeyExcludedFromWebScript:(const char *)name { return NO; } \
-\
-@end
-
-ImplementIterator(VertexNodeIterator, VertexNode, node)
-ImplementIterator(TriangleNodeIterator, TriangleNode, node)
-ImplementIterator(EdgeNodeIterator, VertexEdgeNode, node)
-ImplementIterator(VertexNodeEdgeIterator, Vertex2VEdgeNode, simpleNode)

Classes/MyDocument.cpp

 			setNeedsDisplayOnAllViews();
 		}
 	}
+
+	void MyDocument::runScriptAction(Action<ItemCollectionWrapper ^> ^scriptAction)
+	{
+		this->scriptAction = scriptAction;
+		allItemsAction(L"Script Action", gcnew Action(this, &MyDocument::runScriptActionCore));
+		setNeedsDisplayOnAllViews();
+	}
+
+	void MyDocument::runScriptActionCore()
+	{
+		for (uint i = 0; i < items->count(); i++)
+        {
+            Item *item = items->itemAtIndex(i);
+            item->mesh->resetTriangleCache();
+            item->mesh->resetAlgorithmData();
+        }
+        
+		scriptAction(gcnew ItemCollectionWrapper(items));
+        
+		manipulated->updateSelection();
+	}
 }
 
 #elif defined(__linux__)

Classes/MyDocument.h

 #include "ItemCollection.h"
 #include "OpenGLSceneView.h"
 #include "TextureCollection.h"
+#include "JSWrappers.h"
 #include "../MeshMakerCppCLI/MarshalHelpers.h"
 
 namespace MeshMakerCppCLI
 		UndoStatePointer ^oldManipulations;
 		UndoStatePointer ^oldMeshState;
 
+		Action<ItemCollectionWrapper ^> ^scriptAction;
 	private:
         void setManipulated(IOpenGLManipulating *value);
 		Mesh2 *currentMesh();
 		void allItemsAction(String ^actionName, Action ^action);
 		void meshAction(String ^actionName, Action ^action);
 		void meshOnlyAction(String ^actionName, Action ^action);
+		void runScriptActionCore();
 	public:
 		MyDocument(IDocumentDelegate ^documentForm);
 		~MyDocument();
 		String ^textureNameAtIndex(uint index);
 		Bitmap ^textureImageAtIndex(uint index);
 		void setTextureAtIndex(uint index);
+
+		void runScriptAction(Action<ItemCollectionWrapper ^> ^scriptAction);
 	};
 }
 

Classes/Texture.cpp

 		else if (components == 4)
 		{
 #if defined (WIN32)
-			GLubyte *rgbaData = (GLubyte *)malloc(width * height * components);
-			for (int i = 0; i < width * height; i++)
-			{
-				rgbaData[i * components + 0] = data[i * components + 2];
-				rgbaData[i * components + 1] = data[i * components + 1];
-				rgbaData[i * components + 2] = data[i * components + 0];
-				rgbaData[i * components + 3] = data[i * components + 3];
+			GLubyte *rgbaData = (GLubyte *)malloc(width * height * components);
+			for (int i = 0; i < width * height; i++)
+			{
+				rgbaData[i * components + 0] = data[i * components + 2];
+				rgbaData[i * components + 1] = data[i * components + 1];
+				rgbaData[i * components + 2] = data[i * components + 0];
+				rgbaData[i * components + 3] = data[i * components + 3];
 			}
 			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbaData);
 			free(rgbaData);

MeshMaker/Dependencies/Noesis.Javascript.dll

Binary file added.

MeshMaker/DocumentForm.Designer.cs

             this.triangulateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.viewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.toggleOneViewFourViewsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.textureBrowserToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.toolStripTop = new System.Windows.Forms.ToolStrip();
             this.toolStripButtonSelect = new System.Windows.Forms.ToolStripButton();
             this.toolStripButtonTranslate = new System.Windows.Forms.ToolStripButton();
             this.toolStripTextBoxSelectionY = new System.Windows.Forms.ToolStripTextBox();
             this.toolStripLabel3 = new System.Windows.Forms.ToolStripLabel();
             this.toolStripTextBoxSelectionZ = new System.Windows.Forms.ToolStripTextBox();
-            this.textureBrowserToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.scriptEditorToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             ((System.ComponentModel.ISupportInitialize)(this.mainSplit)).BeginInit();
             this.mainSplit.Panel1.SuspendLayout();
             this.mainSplit.Panel2.SuspendLayout();
             this.frontViewPanel.Dock = System.Windows.Forms.DockStyle.Fill;
             this.frontViewPanel.Location = new System.Drawing.Point(0, 0);
             this.frontViewPanel.Name = "frontViewPanel";
-            this.frontViewPanel.Size = new System.Drawing.Size(431, 229);
+            this.frontViewPanel.Size = new System.Drawing.Size(431, 230);
             this.frontViewPanel.TabIndex = 0;
             // 
             // mainSplit
             // 
             this.mainSplit.Panel2.Controls.Add(this.bottomSplit);
             this.mainSplit.Size = new System.Drawing.Size(862, 461);
-            this.mainSplit.SplitterDistance = 228;
+            this.mainSplit.SplitterDistance = 227;
             this.mainSplit.TabIndex = 1;
             // 
             // topSplit
             // topSplit.Panel2
             // 
             this.topSplit.Panel2.Controls.Add(this.topViewPanel);
-            this.topSplit.Size = new System.Drawing.Size(862, 228);
+            this.topSplit.Size = new System.Drawing.Size(862, 227);
             this.topSplit.SplitterDistance = 431;
             this.topSplit.TabIndex = 2;
             this.topSplit.SplitterMoving += new System.Windows.Forms.SplitterCancelEventHandler(this.topSplit_SplitterMoving);
             this.leftViewPanel.Dock = System.Windows.Forms.DockStyle.Fill;
             this.leftViewPanel.Location = new System.Drawing.Point(0, 0);
             this.leftViewPanel.Name = "leftViewPanel";
-            this.leftViewPanel.Size = new System.Drawing.Size(431, 228);
+            this.leftViewPanel.Size = new System.Drawing.Size(431, 227);
             this.leftViewPanel.TabIndex = 0;
             // 
             // topViewPanel
             this.topViewPanel.Dock = System.Windows.Forms.DockStyle.Fill;
             this.topViewPanel.Location = new System.Drawing.Point(0, 0);
             this.topViewPanel.Name = "topViewPanel";
-            this.topViewPanel.Size = new System.Drawing.Size(427, 228);
+            this.topViewPanel.Size = new System.Drawing.Size(427, 227);
             this.topViewPanel.TabIndex = 0;
             // 
             // bottomSplit
             // bottomSplit.Panel2
             // 
             this.bottomSplit.Panel2.Controls.Add(this.perspectiveViewPanel);
-            this.bottomSplit.Size = new System.Drawing.Size(862, 229);
+            this.bottomSplit.Size = new System.Drawing.Size(862, 230);
             this.bottomSplit.SplitterDistance = 431;
             this.bottomSplit.TabIndex = 2;
             this.bottomSplit.SplitterMoving += new System.Windows.Forms.SplitterCancelEventHandler(this.bottomSplit_SplitterMoving);
             this.perspectiveViewPanel.Dock = System.Windows.Forms.DockStyle.Fill;
             this.perspectiveViewPanel.Location = new System.Drawing.Point(0, 0);
             this.perspectiveViewPanel.Name = "perspectiveViewPanel";
-            this.perspectiveViewPanel.Size = new System.Drawing.Size(427, 229);
+            this.perspectiveViewPanel.Size = new System.Drawing.Size(427, 230);
             this.perspectiveViewPanel.TabIndex = 0;
             // 
             // menuStrip1
             // 
             this.viewToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
             this.toggleOneViewFourViewsToolStripMenuItem,
-            this.textureBrowserToolStripMenuItem});
+            this.textureBrowserToolStripMenuItem,
+            this.scriptEditorToolStripMenuItem});
             this.viewToolStripMenuItem.Name = "viewToolStripMenuItem";
             this.viewToolStripMenuItem.Size = new System.Drawing.Size(44, 20);
             this.viewToolStripMenuItem.Text = "View";
             this.toggleOneViewFourViewsToolStripMenuItem.Text = "Toggle One View/Four Views";
             this.toggleOneViewFourViewsToolStripMenuItem.Click += new System.EventHandler(this.toggleOneViewFourViewMenuItem_Click);
             // 
+            // textureBrowserToolStripMenuItem
+            // 
+            this.textureBrowserToolStripMenuItem.Name = "textureBrowserToolStripMenuItem";
+            this.textureBrowserToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.B)));
+            this.textureBrowserToolStripMenuItem.Size = new System.Drawing.Size(264, 22);
+            this.textureBrowserToolStripMenuItem.Text = "Texture Browser";
+            this.textureBrowserToolStripMenuItem.Click += new System.EventHandler(this.textureBrowserToolStripMenuItem_Click);
+            // 
             // toolStripTop
             // 
             this.toolStripTop.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
             this.toolStripTextBoxSelectionZ.Leave += new System.EventHandler(this.selectionLeave);
             this.toolStripTextBoxSelectionZ.KeyDown += new System.Windows.Forms.KeyEventHandler(this.selectionKeyDown);
             // 
-            // textureBrowserToolStripMenuItem
+            // scriptEditorToolStripMenuItem
             // 
-            this.textureBrowserToolStripMenuItem.Name = "textureBrowserToolStripMenuItem";
-            this.textureBrowserToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.B)));
-            this.textureBrowserToolStripMenuItem.Size = new System.Drawing.Size(264, 22);
-            this.textureBrowserToolStripMenuItem.Text = "Texture Browser";
-            this.textureBrowserToolStripMenuItem.Click += new System.EventHandler(this.textureBrowserToolStripMenuItem_Click);
+            this.scriptEditorToolStripMenuItem.Name = "scriptEditorToolStripMenuItem";
+            this.scriptEditorToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.E)));
+            this.scriptEditorToolStripMenuItem.Size = new System.Drawing.Size(264, 22);
+            this.scriptEditorToolStripMenuItem.Text = "Script Editor";
+            this.scriptEditorToolStripMenuItem.Click += new System.EventHandler(this.scriptEditorToolStripMenuItem_Click);
             // 
             // DocumentForm
             // 
         private System.Windows.Forms.ToolStripButton toolStripButtonColor;
         private System.Windows.Forms.ToolStripSeparator toolStripSeparator12;
         private System.Windows.Forms.ToolStripMenuItem textureBrowserToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem scriptEditorToolStripMenuItem;
     }
 }
 

MeshMaker/DocumentForm.cs

         ToolStripButton[] manipulatorButtons;
 
         TextureBrowser textureBrowser;
+        ScriptEditor scriptEditor;
         
         public DocumentForm()
         {
             if (!textureBrowser.Visible)
                 textureBrowser.Show();
         }
+
+        private void scriptEditorToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (scriptEditor == null || scriptEditor.IsDisposed)
+                scriptEditor = new ScriptEditor(document);
+
+            if (!scriptEditor.Visible)
+                scriptEditor.Show();
+        }
     }
 }

MeshMaker/MeshMaker.csproj

     <PlatformTarget>x86</PlatformTarget>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="Noesis.Javascript">
+      <HintPath>Dependencies\Noesis.Javascript.dll</HintPath>
+    </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core">
       <RequiredTargetFramework>3.5</RequiredTargetFramework>
     </Compile>
     <Compile Include="Program.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="ScriptEditor.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="ScriptEditor.Designer.cs">
+      <DependentUpon>ScriptEditor.cs</DependentUpon>
+    </Compile>
     <Compile Include="TextureBrowser.cs">
       <SubType>Form</SubType>
     </Compile>
       <DependentUpon>Resources.resx</DependentUpon>
       <DesignTime>True</DesignTime>
     </Compile>
+    <EmbeddedResource Include="ScriptEditor.resx">
+      <DependentUpon>ScriptEditor.cs</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="TextureBrowser.resx">
       <DependentUpon>TextureBrowser.cs</DependentUpon>
     </EmbeddedResource>

MeshMaker/ScriptEditor.Designer.cs

+namespace MeshMaker
+{
+    partial class ScriptEditor
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ScriptEditor));
+            this.toolStrip1 = new System.Windows.Forms.ToolStrip();
+            this.toolStripButtonNewScript = new System.Windows.Forms.ToolStripButton();
+            this.toolStripButtonRunScript = new System.Windows.Forms.ToolStripButton();
+            this.textBoxCode = new System.Windows.Forms.TextBox();
+            this.textBoxOutput = new System.Windows.Forms.TextBox();
+            this.listBoxScripts = new System.Windows.Forms.ListBox();
+            this.splitContainer1 = new System.Windows.Forms.SplitContainer();
+            this.splitContainer2 = new System.Windows.Forms.SplitContainer();
+            this.toolStrip1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
+            this.splitContainer1.Panel1.SuspendLayout();
+            this.splitContainer1.Panel2.SuspendLayout();
+            this.splitContainer1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit();
+            this.splitContainer2.Panel1.SuspendLayout();
+            this.splitContainer2.Panel2.SuspendLayout();
+            this.splitContainer2.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // toolStrip1
+            // 
+            this.toolStrip1.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
+            this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.toolStripButtonNewScript,
+            this.toolStripButtonRunScript});
+            this.toolStrip1.Location = new System.Drawing.Point(0, 0);
+            this.toolStrip1.Name = "toolStrip1";
+            this.toolStrip1.Size = new System.Drawing.Size(851, 25);
+            this.toolStrip1.TabIndex = 0;
+            this.toolStrip1.Text = "toolStrip1";
+            // 
+            // toolStripButtonNewScript
+            // 
+            this.toolStripButtonNewScript.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButtonNewScript.Image")));
+            this.toolStripButtonNewScript.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.toolStripButtonNewScript.Name = "toolStripButtonNewScript";
+            this.toolStripButtonNewScript.Size = new System.Drawing.Size(84, 22);
+            this.toolStripButtonNewScript.Text = "New Script";
+            this.toolStripButtonNewScript.Click += new System.EventHandler(this.toolStripButtonNewScript_Click);
+            // 
+            // toolStripButtonRunScript
+            // 
+            this.toolStripButtonRunScript.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButtonRunScript.Image")));
+            this.toolStripButtonRunScript.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.toolStripButtonRunScript.Name = "toolStripButtonRunScript";
+            this.toolStripButtonRunScript.Size = new System.Drawing.Size(81, 22);
+            this.toolStripButtonRunScript.Text = "Run Script";
+            this.toolStripButtonRunScript.Click += new System.EventHandler(this.toolStripButtonRunScript_Click);
+            // 
+            // textBoxCode
+            // 
+            this.textBoxCode.AcceptsReturn = true;
+            this.textBoxCode.AcceptsTab = true;
+            this.textBoxCode.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.textBoxCode.Font = new System.Drawing.Font("Courier New", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
+            this.textBoxCode.Location = new System.Drawing.Point(0, 0);
+            this.textBoxCode.Multiline = true;
+            this.textBoxCode.Name = "textBoxCode";
+            this.textBoxCode.Size = new System.Drawing.Size(686, 437);
+            this.textBoxCode.TabIndex = 1;
+            // 
+            // textBoxOutput
+            // 
+            this.textBoxOutput.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.textBoxOutput.Font = new System.Drawing.Font("Courier New", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
+            this.textBoxOutput.Location = new System.Drawing.Point(0, 0);
+            this.textBoxOutput.Multiline = true;
+            this.textBoxOutput.Name = "textBoxOutput";
+            this.textBoxOutput.ReadOnly = true;
+            this.textBoxOutput.Size = new System.Drawing.Size(686, 112);
+            this.textBoxOutput.TabIndex = 2;
+            this.textBoxOutput.Text = "Output:";
+            // 
+            // listBoxScripts
+            // 
+            this.listBoxScripts.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.listBoxScripts.FormattingEnabled = true;
+            this.listBoxScripts.Location = new System.Drawing.Point(0, 0);
+            this.listBoxScripts.Name = "listBoxScripts";
+            this.listBoxScripts.Size = new System.Drawing.Size(161, 553);
+            this.listBoxScripts.TabIndex = 3;
+            this.listBoxScripts.SelectedIndexChanged += new System.EventHandler(this.listBoxScripts_SelectedIndexChanged);
+            // 
+            // splitContainer1
+            // 
+            this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.splitContainer1.Location = new System.Drawing.Point(0, 0);
+            this.splitContainer1.Name = "splitContainer1";
+            this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
+            // 
+            // splitContainer1.Panel1
+            // 
+            this.splitContainer1.Panel1.Controls.Add(this.textBoxCode);
+            // 
+            // splitContainer1.Panel2
+            // 
+            this.splitContainer1.Panel2.Controls.Add(this.textBoxOutput);
+            this.splitContainer1.Size = new System.Drawing.Size(686, 553);
+            this.splitContainer1.SplitterDistance = 437;
+            this.splitContainer1.TabIndex = 4;
+            // 
+            // splitContainer2
+            // 
+            this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.splitContainer2.Location = new System.Drawing.Point(0, 25);
+            this.splitContainer2.Name = "splitContainer2";
+            // 
+            // splitContainer2.Panel1
+            // 
+            this.splitContainer2.Panel1.Controls.Add(this.listBoxScripts);
+            // 
+            // splitContainer2.Panel2
+            // 
+            this.splitContainer2.Panel2.Controls.Add(this.splitContainer1);
+            this.splitContainer2.Size = new System.Drawing.Size(851, 553);
+            this.splitContainer2.SplitterDistance = 161;
+            this.splitContainer2.TabIndex = 5;
+            // 
+            // ScriptEditor
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(851, 578);
+            this.Controls.Add(this.splitContainer2);
+            this.Controls.Add(this.toolStrip1);
+            this.Name = "ScriptEditor";
+            this.Text = "Script Editor";
+            this.toolStrip1.ResumeLayout(false);
+            this.toolStrip1.PerformLayout();
+            this.splitContainer1.Panel1.ResumeLayout(false);
+            this.splitContainer1.Panel1.PerformLayout();
+            this.splitContainer1.Panel2.ResumeLayout(false);
+            this.splitContainer1.Panel2.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
+            this.splitContainer1.ResumeLayout(false);
+            this.splitContainer2.Panel1.ResumeLayout(false);
+            this.splitContainer2.Panel2.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit();
+            this.splitContainer2.ResumeLayout(false);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.ToolStrip toolStrip1;
+        private System.Windows.Forms.ToolStripButton toolStripButtonNewScript;
+        private System.Windows.Forms.ToolStripButton toolStripButtonRunScript;
+        private System.Windows.Forms.TextBox textBoxCode;
+        private System.Windows.Forms.TextBox textBoxOutput;
+        private System.Windows.Forms.ListBox listBoxScripts;
+        private System.Windows.Forms.SplitContainer splitContainer1;
+        private System.Windows.Forms.SplitContainer splitContainer2;
+    }
+}

MeshMaker/ScriptEditor.cs

+using MeshMakerCppCLI;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using Noesis.Javascript;
+
+namespace MeshMaker
+{
+    public partial class ScriptEditor : Form
+    {
+        MyDocument document;
+
+        class JSWindow
+        {
+            ScriptEditor _editor;
+
+            public JSWindow(ScriptEditor editor) { _editor = editor; }
+
+            public void alert(string text)
+            {
+                _editor.textBoxOutput.AppendText(text + Environment.NewLine);
+            }
+        }
+
+        public ScriptEditor(MyDocument document)
+        {
+            InitializeComponent();
+            this.document = document;
+        }
+
+        private void toolStripButtonNewScript_Click(object sender, EventArgs e)
+        {
+
+        }
+
+        private void toolStripButtonRunScript_Click(object sender, EventArgs e)
+        {
+            textBoxOutput.Text = "Output:" + Environment.NewLine;
+
+            document.runScriptAction(items =>
+                {
+                    using (JavascriptContext context = new JavascriptContext())
+                    {
+                        context.SetParameter("window", new JSWindow(this));
+                        context.SetParameter("items", items);
+                        context.Run(textBoxCode.Text);
+                    }
+                });
+        }
+
+        private void listBoxScripts_SelectedIndexChanged(object sender, EventArgs e)
+        {
+
+        }
+    }
+}

MeshMaker/ScriptEditor.resx

+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="toolStripButtonNewScript.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIISURBVDhPpZP7S1NxGMbPPxKaXVUkMEq8IpKUCoY/hGgI
+        ymqkDYYXcCjDZOANURSjCNGFQUTsl4GXVMxKk62YU4fXQpaIlygHQxBRH8/zwvyaIAYe+HLgnPN8nue9
+        HA3nvDTq63oW/jm13XOwvPTB3DYFY5MH+bXfcN8ygfTSMSSXfESicQDxBqdYHwH29g9w2tnZ3UcguIvN
+        rR3417exuBJE5N1n/wfwLgXEOc38Bc6xNRHb+/y4nm49G0Bnit2zf9H6bkliE/jKuYxrd6oVgDWfjB+K
+        TWeKMyrGEVfowITvD9re/9ABVQrAhh0HHK+ZselMMaN/mvwtDb+aVqkA7HYIwIj3ysfluPTorJnP6Ezx
+        oHsD1s5ZXEktUwCOioB5f1CEPR9+wTG6iuiserTo8dkwng7HT/R+XUPF8xlcTjErAOdMcW6NW8STiwG8
+        7vej8oUPN/PsEv3t8Ao0TZP3T1u8uJRkUgAuSYHtO97oLxmXd5t9Ho8aPTK+GzntqNfrLm2fFoihwYOI
+        xGIF4KjoGBLzY1OrF9k6OOFxnwDC4wxIMX1G0pMhgVyMNyoA13PAtS7OrJk1PrC69LUdQWxuF6IybHrX
+        LRI7JrtZdoDAo1XmbjMyD+tjSXxGcXRmnYg5ttD9QuxDhN0uUgDOmbvNTpPOJaGAo2K36cyaGZvOFIfd
+        KlSA8/zRh9ABIDUG+1JpAAAAAElFTkSuQmCC
+</value>
+  </data>
+  <data name="toolStripButtonRunScript.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIISURBVDhPpZP7S1NxGMbPPxKaXVUkMEq8IpKUCoY/hGgI
+        ymqkDYYXcCjDZOANURSjCNGFQUTsl4GXVMxKk62YU4fXQpaIlygHQxBRH8/zwvyaIAYe+HLgnPN8nue9
+        HA3nvDTq63oW/jm13XOwvPTB3DYFY5MH+bXfcN8ygfTSMSSXfESicQDxBqdYHwH29g9w2tnZ3UcguIvN
+        rR3417exuBJE5N1n/wfwLgXEOc38Bc6xNRHb+/y4nm49G0Bnit2zf9H6bkliE/jKuYxrd6oVgDWfjB+K
+        TWeKMyrGEVfowITvD9re/9ABVQrAhh0HHK+ZselMMaN/mvwtDb+aVqkA7HYIwIj3ysfluPTorJnP6Ezx
+        oHsD1s5ZXEktUwCOioB5f1CEPR9+wTG6iuiserTo8dkwng7HT/R+XUPF8xlcTjErAOdMcW6NW8STiwG8
+        7vej8oUPN/PsEv3t8Ao0TZP3T1u8uJRkUgAuSYHtO97oLxmXd5t9Ho8aPTK+GzntqNfrLm2fFoihwYOI
+        xGIF4KjoGBLzY1OrF9k6OOFxnwDC4wxIMX1G0pMhgVyMNyoA13PAtS7OrJk1PrC69LUdQWxuF6IybHrX
+        LRI7JrtZdoDAo1XmbjMyD+tjSXxGcXRmnYg5ttD9QuxDhN0uUgDOmbvNTpPOJaGAo2K36cyaGZvOFIfd
+        KlSA8/zRh9ABIDUG+1JpAAAAAElFTkSuQmCC
+</value>
+  </data>
+</root>

MeshMakerCppCLI/MeshMakerCppCLI.vcxproj

   <ItemGroup>
     <ClCompile Include="..\Classes\Item.cpp" />
     <ClCompile Include="..\Classes\ItemCollection.cpp" />
+    <ClCompile Include="..\Classes\JSWrappers.cpp" />
     <ClCompile Include="..\Classes\Manipulator.cpp" />
     <ClCompile Include="..\Classes\ManipulatorWidget.cpp" />
     <ClCompile Include="..\Classes\MemoryStream.cpp" />
     <ClInclude Include="..\Classes\FPNode.h" />
     <ClInclude Include="..\Classes\Item.h" />
     <ClInclude Include="..\Classes\ItemCollection.h" />
+    <ClInclude Include="..\Classes\JSWrappers.h" />
     <ClInclude Include="..\Classes\Manipulator.h" />
     <ClInclude Include="..\Classes\ManipulatorWidget.h" />
     <ClInclude Include="..\Classes\Texture.h" />

MeshMakerCppCLI/MeshMakerCppCLI.vcxproj.filters

     <ClCompile Include="..\Classes\TextureCollection.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\Classes\JSWrappers.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\Classes\Camera.h">
     <ClInclude Include="..\Classes\Exceptions.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\Classes\JSWrappers.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <Image Include="app.ico">