Skip to content

Commit af1c899

Browse files
committed
Add material command
1 parent 6289c52 commit af1c899

File tree

6 files changed

+98
-10
lines changed

6 files changed

+98
-10
lines changed

ShapeScript/Interpreter.swift

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,16 @@ extension Statement {
977977
}
978978
case let .expression(type):
979979
let expression = Expression(type: type, range: range)
980-
try RuntimeError.wrap(context.addValue(expression.evaluate(in: context)), at: range)
980+
do {
981+
try context.addValue(expression.evaluate(in: context))
982+
} catch let error as RuntimeErrorType {
983+
// TODO: generalize this
984+
guard case .unusedValue(type: ValueType.material.errorDescription) = error,
985+
case .block = type
986+
else {
987+
throw RuntimeError(error, at: range)
988+
}
989+
}
981990
case let .define(identifier, definition):
982991
switch definition.type {
983992
case let .function(names, _):
@@ -1154,7 +1163,7 @@ extension Expression {
11541163
guard let value = value.as(.list(.path)) ?? value.as(.list(.mesh)),
11551164
case let .tuple(values) = value
11561165
else {
1157-
fallthrough
1166+
throw RuntimeError(.unexpectedArgument(for: name, max: 0), at: block.range)
11581167
}
11591168
let sourceIndex = context.sourceIndex
11601169
let newContext = context.push(.init(.transform, [:], .mesh, value.type))
@@ -1171,11 +1180,47 @@ extension Expression {
11711180
return .tuple(values.map {
11721181
.mesh(($0.value as! Geometry).transformed(by: newContext.transform))
11731182
})
1174-
case .property, .function((.void, _), _):
1175-
throw RuntimeError(
1176-
.unexpectedArgument(for: name, max: 0),
1177-
at: block.range
1178-
)
1183+
case let .property(type, setter, _):
1184+
switch type {
1185+
case .material:
1186+
// TODO: generalize this
1187+
let blockType = BlockType([:], [
1188+
"color": .color,
1189+
"opacity": .number,
1190+
"texture": .texture,
1191+
"metallicity": .colorOrTexture,
1192+
"roughness": .colorOrTexture,
1193+
"glow": .colorOrTexture,
1194+
], .void, .material)
1195+
let newContext = context.push(blockType)
1196+
try newContext.pushScope { newContext in
1197+
block.statements.gatherDefinitions(in: newContext)
1198+
for statement in block.statements {
1199+
try statement.evaluate(in: newContext)
1200+
}
1201+
}
1202+
let diffuse = newContext.value(for: "color") ?? newContext.value(for: "texure")
1203+
let material = Material(
1204+
opacity: newContext.value(for: "opacity")?.doubleValue ?? 1,
1205+
diffuse: diffuse?.colorOrTextureValue,
1206+
metallicity: newContext.value(for: "metallicity")?.colorOrTextureValue,
1207+
roughness: newContext.value(for: "roughness")?.colorOrTextureValue,
1208+
glow: newContext.value(for: "glow")?.colorOrTextureValue
1209+
)
1210+
try RuntimeError.wrap(setter(.material(material), context), at: range)
1211+
return .material(material)
1212+
case .object, .any, .color, .texture, .boolean, .font, .number, .radians,
1213+
.halfturns, .vector, .size, .rotation, .string, .text, .path,
1214+
.mesh, .polygon, .point, .range, .bounds, .union, .tuple, .list:
1215+
break
1216+
}
1217+
throw RuntimeError(.typeMismatch(
1218+
for: name,
1219+
expected: type.errorDescription,
1220+
got: "block"
1221+
), at: block.range)
1222+
case .function((.void, _), _):
1223+
throw RuntimeError(.unexpectedArgument(for: name, max: 0), at: block.range)
11791224
case let .function((type, _), _):
11801225
throw RuntimeError(.typeMismatch(
11811226
for: name,

ShapeScript/StandardLibrary.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ extension Dictionary where Key == String, Value == Symbol {
114114
}, { context in
115115
.colorOrTexture(context.material.glow ?? .color(.black))
116116
}),
117+
"material": .property(.material, { parameter, context in
118+
context.material = parameter.value as? Material ?? .default
119+
}, { context in
120+
.material(context.material)
121+
}),
117122
]
118123

119124
static let polygons: Symbols = [

ShapeScriptTests/InterpreterTests.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,6 +1415,44 @@ class InterpreterTests: XCTestCase {
14151415
}
14161416
}
14171417

1418+
// MARK: Material
1419+
1420+
func testDefaultMaterial() {
1421+
let program = """
1422+
print color
1423+
print material.color
1424+
"""
1425+
let delegate = TestDelegate()
1426+
XCTAssertNoThrow(try evaluate(parse(program), delegate: delegate))
1427+
XCTAssertEqual(delegate.log, [Color.white, .white])
1428+
}
1429+
1430+
func testColorMaterial() {
1431+
let program = """
1432+
material {
1433+
color (1 0 0)
1434+
}
1435+
print color
1436+
print material.color
1437+
"""
1438+
let delegate = TestDelegate()
1439+
XCTAssertNoThrow(try evaluate(parse(program), delegate: delegate))
1440+
XCTAssertEqual(delegate.log, [Color.red, .red])
1441+
}
1442+
1443+
func testStoredMaterial() {
1444+
let program = """
1445+
define foo material {
1446+
color (1 0 0)
1447+
}
1448+
print color
1449+
print foo.color
1450+
"""
1451+
let delegate = TestDelegate()
1452+
XCTAssertNoThrow(try evaluate(parse(program), delegate: delegate))
1453+
XCTAssertEqual(delegate.log, [Color.white, .red])
1454+
}
1455+
14181456
// MARK: Background
14191457

14201458
func testSetBackgroundColorWithParens() throws {

docs/ios/commands.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ The `smoothing` command can be used anywhere in the ShapeScript file to override
5555

5656
## Materials
5757

58-
The `color`, `texture` and `opacity` commands are used to specify the appearance of shapes when rendered. These commands are documented in the [materials](materials.md) section.
58+
The `material` command (along with individual material property commands such as `color` and `texture`) are used to specify the appearance of shapes when rendered. These commands are documented in the [materials](materials.md) section.
5959

6060
## Font
6161

docs/mac/commands.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ The `smoothing` command can be used anywhere in the ShapeScript file to override
5555

5656
## Materials
5757

58-
The `color`, `texture` and `opacity` commands are used to specify the appearance of shapes when rendered. These commands are documented in the [materials](materials.md) section.
58+
The `material` command (along with individual material property commands such as `color` and `texture`) are used to specify the appearance of shapes when rendered. These commands are documented in the [materials](materials.md) section.
5959

6060
## Font
6161

docs/src/commands.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ The `smoothing` command can be used anywhere in the ShapeScript file to override
5555

5656
## Materials
5757

58-
The `color`, `texture` and `opacity` commands are used to specify the appearance of shapes when rendered. These commands are documented in the [materials](materials.md) section.
58+
The `material` command (along with individual material property commands such as `color` and `texture`) are used to specify the appearance of shapes when rendered. These commands are documented in the [materials](materials.md) section.
5959

6060
## Font
6161

0 commit comments

Comments
 (0)