diff --git a/lib/layout/dialogs/common/clear_dialog.dart b/lib/layout/dialogs/common/clear_dialog.dart index 876fe7e..c371e27 100755 --- a/lib/layout/dialogs/common/clear_dialog.dart +++ b/lib/layout/dialogs/common/clear_dialog.dart @@ -14,6 +14,7 @@ class ClearDialog extends StatefulWidget { class _ClearDialogState extends State { final _widthController = TextEditingController(); final _heightController = TextEditingController(); + var useBorder = false; @override void dispose() { @@ -37,27 +38,41 @@ class _ClearDialogState extends State { height: 20.h, child: LayoutBuilder(builder: (context, constraints) { return Center( - child: Row( + child: Column( children: [ - Spacer(), - SizedBox( - width: constraints.maxWidth / 3, - height: 7.h, - child: TextBox( - prefix: Text('Width'), - controller: _widthController, - ), + Row( + children: [ + Spacer(), + SizedBox( + width: constraints.maxWidth / 3, + height: 7.h, + child: TextBox( + prefix: Text('Width'), + controller: _widthController, + ), + ), + SizedBox(width: constraints.maxWidth / 10), + SizedBox( + width: constraints.maxWidth / 3, + height: 7.h, + child: TextBox( + prefix: Text('Height'), + controller: _heightController, + ), + ), + Spacer(), + ], ), - SizedBox(width: constraints.maxWidth / 10), - SizedBox( - width: constraints.maxWidth / 3, - height: 7.h, - child: TextBox( - prefix: Text('Height'), - controller: _heightController, - ), + SizedBox(height: constraints.maxHeight / 20), + Row( + children: [ + Spacer(), + Text("Use Selected Cell as Border"), + SizedBox(width: constraints.maxWidth / 20), + Checkbox(checked: useBorder, onChanged: (v) => setState(() => useBorder = v ?? useBorder)), + Spacer(), + ], ), - Spacer(), ], ), ); @@ -81,13 +96,28 @@ class _ClearDialogState extends State { game.isinitial = true; game.initial = grid.copy; game.itime = 0; + final g = Grid(w, h); + if(useBorder) { + final c = game.currentSelection; + + for(var x = 0; x < w; x++) { + g.set(x, 0, Cell(x, 0)..id = c); + g.set(x, h - 1, Cell(x, h - 1)..id = c); + } + + for(var y = 0; y < h; y++) { + g.set(0, y, Cell(0, y)..id = c); + g.set(w - 1, y, Cell(w - 1, y)..id = c); + } + } + if (game.isMultiplayer) { game.sendToServer( 'setinit', - {"code": SavingFormat.encodeGrid(Grid(w, h))}, + {"code": SavingFormat.encodeGrid(g)}, ); } else { - grid = Grid(w, h); + grid = g; } game.buildEmpty(); game.overlays.remove("EditorMenu"); diff --git a/lib/layout/dialogs/common/property_editor_dialog.dart b/lib/layout/dialogs/common/property_editor_dialog.dart index 0f7086c..fef9e8c 100755 --- a/lib/layout/dialogs/common/property_editor_dialog.dart +++ b/lib/layout/dialogs/common/property_editor_dialog.dart @@ -34,199 +34,39 @@ class _PropertyEditorDialogState extends State { } } - Widget propToTile(int i) { - final property = props[game.currentSelection]![i]; - - final displayName = lang("property.${game.currentSelection}.${property.key}.name", property.name); - + Widget indexToBody(int i, BuildContext ctx) { final textStyle = TextStyle(fontSize: 5.sp); + final property = props[game.currentSelection]![i]; if (property.type == CellPropertyType.cellID) { - final currentID = controllers[i].text; - final tp = textureMap['$currentID.png'] ?? '$currentID.png'; - return DropDownButton( - leading: Image.asset( - 'assets/images/$tp', - fit: BoxFit.fill, - colorBlendMode: BlendMode.clear, - filterQuality: FilterQuality.none, - isAntiAlias: true, - width: 3.h, - height: 3.h, - ), - title: Text("$displayName: ${idToString(currentID)}", style: textStyle), - items: [ - for (var id in (cells..removeWhere((v) => backgrounds.contains(v)))) - MenuFlyoutItem( - leading: Image.asset( - 'assets/images/${textureMap["$id.png"] ?? "$id.png"}', - fit: BoxFit.fill, - colorBlendMode: BlendMode.clear, - filterQuality: FilterQuality.none, - isAntiAlias: true, - width: 3.h, - height: 3.h, - ), - text: Text(idToString(id), style: textStyle), - onPressed: () { - controllers[i].text = id; - setState(() {}); - }, - ), - ], - ); - } - if (property.type == CellPropertyType.cellRot) { - final currentID = controllers[i].text; - final rot = int.tryParse(currentID) ?? 0; - - return DropDownButton( - title: Text("$displayName: ${rotToString(rot)}"), - items: [ - for (var r = 0; r < 4; r++) - MenuFlyoutItem( - text: Text(rotToString(rot), style: textStyle), - onPressed: () { - controllers[i].text = r.toString(); - setState(() {}); - }, + var currentID = controllers[i].text; + var tp = textureMap['$currentID.png'] ?? '$currentID.png'; + return StatefulBuilder( + builder: (ctx, setState) { + return ListTile( + leading: Image.asset( + 'assets/images/$tp', + fit: BoxFit.fill, + colorBlendMode: BlendMode.clear, + filterQuality: FilterQuality.none, + isAntiAlias: true, + width: 3.h, + height: 3.h, ), - ], - ); - } - if (property.type == CellPropertyType.cell) { - final current = controllers[i].text; - - final (currentId, currentRot) = parseJointCellStr(current); - - return DropDownButton( - leading: Transform.rotate( - angle: currentRot * halfPi, - child: Image.asset( - idToTexture(currentId), - fit: BoxFit.fill, - colorBlendMode: BlendMode.clear, - filterQuality: FilterQuality.none, - isAntiAlias: true, - width: 3.h, - height: 3.h, - ), - ), - title: Text("$displayName: ${idToString(currentId)} (${rotToString(currentRot)})", style: textStyle), - items: [ - for (var id in (cells..removeWhere((v) => backgrounds.contains(v)))) - for (var r = 0; r < 4; r++) - MenuFlyoutItem( - leading: Transform.rotate( - angle: r * halfPi, - child: Image.asset( - idToTexture(id), - fit: BoxFit.fill, - colorBlendMode: BlendMode.clear, - filterQuality: FilterQuality.none, - isAntiAlias: true, - width: 3.h, - height: 3.h, - ), - ), - text: Text("${idToString(id)} (${rotToString(r)})", style: textStyle), - onPressed: () { - controllers[i].text = "$id!$r"; + title: Text("Current: ${idToString(currentID)}", style: textStyle), + onPressed: () { + showDialog( + builder: (ctx) => SearchCellDialog(currentSelection: currentID, onChanged: (value) { + controllers[i].text = value; + currentID = value; + tp = textureMap['$currentID.png'] ?? '$currentID.png'; setState(() {}); - }, - ), - ], - ); - } - if (property.type == CellPropertyType.background) { - final currentID = controllers[i].text; - final tp = textureMap['$currentID.png'] ?? '$currentID.png'; - return DropDownButton( - leading: Image.asset( - 'assets/images/$tp', - fit: BoxFit.fill, - colorBlendMode: BlendMode.clear, - filterQuality: FilterQuality.none, - isAntiAlias: true, - width: 3.h, - height: 3.h, - ), - title: Text("$displayName: ${idToString(currentID)}", style: textStyle), - items: [ - for (var id in backgrounds) - MenuFlyoutItem( - leading: Image.asset( - 'assets/images/${textureMap["$id.png"] ?? "$id.png"}', - fit: BoxFit.fill, - colorBlendMode: BlendMode.clear, - filterQuality: FilterQuality.none, - isAntiAlias: true, - width: 3.h, - height: 3.h, - ), - text: Text(idToString(id)), - onPressed: () { - controllers[i].text = id; - setState(() {}); - }, - ), - ], - ); - } - if (property.type == CellPropertyType.boolean) { - return Checkbox( - checked: controllers[i].text == "true", - onChanged: (v) { - controllers[i].text = (v == true) ? "true" : "false"; - setState(() {}); + }), + context: ctx, + ); + } + ); }, - content: Text(displayName, style: textStyle), - ); - } - return TextBox( - prefix: Text(displayName, style: textStyle), - controller: controllers[i], - style: textStyle, - ); - } - - Widget indexToBody(int i) { - final textStyle = TextStyle(fontSize: 5.sp); - final property = props[game.currentSelection]![i]; - - if (property.type == CellPropertyType.cellID) { - final currentID = controllers[i].text; - final tp = textureMap['$currentID.png'] ?? '$currentID.png'; - return DropDownButton( - leading: Image.asset( - 'assets/images/$tp', - fit: BoxFit.fill, - colorBlendMode: BlendMode.clear, - filterQuality: FilterQuality.none, - isAntiAlias: true, - width: 3.h, - height: 3.h, - ), - title: Text("Current: ${idToString(currentID)}", style: textStyle), - items: [ - for (var id in (cells..removeWhere((v) => backgrounds.contains(v)))) - MenuFlyoutItem( - leading: Image.asset( - 'assets/images/${textureMap["$id.png"] ?? "$id.png"}', - fit: BoxFit.fill, - colorBlendMode: BlendMode.clear, - filterQuality: FilterQuality.none, - isAntiAlias: true, - width: 3.h, - height: 3.h, - ), - text: Text(idToString(id), style: textStyle), - onPressed: () { - controllers[i].text = id; - setState(() {}); - }, - ), - ], ); } if (property.type == CellPropertyType.cellRot) { @@ -238,7 +78,7 @@ class _PropertyEditorDialogState extends State { items: [ for (var r = 0; r < 4; r++) MenuFlyoutItem( - text: Text(rotToString(rot), style: textStyle), + text: Text(rotToString(r), style: textStyle), onPressed: () { controllers[i].text = r.toString(); setState(() {}); @@ -250,44 +90,58 @@ class _PropertyEditorDialogState extends State { if (property.type == CellPropertyType.cell) { final current = controllers[i].text; - final (currentId, currentRot) = parseJointCellStr(current); + var (currentId, currentRot) = parseJointCellStr(current); - return DropDownButton( - leading: Transform.rotate( - angle: currentRot * halfPi, - child: Image.asset( - idToTexture(currentId), - fit: BoxFit.fill, - colorBlendMode: BlendMode.clear, - filterQuality: FilterQuality.none, - isAntiAlias: true, - width: 3.h, - height: 3.h, - ), - ), - title: Text("Current: ${idToString(currentId)} (${rotToString(currentRot)})", style: textStyle), - items: [ - for (var id in (cells..removeWhere((v) => backgrounds.contains(v)))) - for (var r = 0; r < 4; r++) - MenuFlyoutItem( - leading: Transform.rotate( - angle: r * halfPi, - child: Image.asset( - idToTexture(id), - fit: BoxFit.fill, - colorBlendMode: BlendMode.clear, - filterQuality: FilterQuality.none, - isAntiAlias: true, - width: 3.h, - height: 3.h, + return Row( + children: [ + StatefulBuilder( + builder: (ctx, setState) { + return SizedBox( + width: 10.w, + child: ListTile( + leading: Transform.rotate( + angle: currentRot * halfPi, + child: Image.asset( + idToTexture(currentId), + fit: BoxFit.fill, + colorBlendMode: BlendMode.clear, + filterQuality: FilterQuality.none, + isAntiAlias: true, + width: 3.h, + height: 3.h, + ), ), + title: Text("Current: ${idToString(currentId)}", style: textStyle), + onPressed: () { + showDialog( + builder: (ctx) => SearchCellDialog(currentSelection: currentId, onChanged: (value) { + controllers[i].text = "$currentId!$currentRot"; + currentId = value; + setState(() {}); + }), + context: ctx, + ); + }, ), - text: Text("${idToString(id)} (${rotToString(r)})", style: textStyle), - onPressed: () { - controllers[i].text = "$id!$r"; - setState(() {}); - }, - ), + ); + }, + ), + SizedBox( + width: 7.w, + child: DropDownButton( + title: Text(rotToString(currentRot)), + items: [ + for (var r = 0; r < 4; r++) + MenuFlyoutItem( + text: Text(rotToString(r), style: textStyle), + onPressed: () { + controllers[i].text = "$currentId!$currentRot"; + setState(() {}); + }, + ), + ], + ), + ), ], ); } @@ -407,7 +261,7 @@ class _PropertyEditorDialogState extends State { style: TextStyle(fontSize: 7.sp), ), ), - indexToBody(currentProperty!), + indexToBody(currentProperty!, context), ], ), ), diff --git a/lib/layout/dialogs/common/search_dialog.dart b/lib/layout/dialogs/common/search_dialog.dart index 720fca2..a494227 100755 --- a/lib/layout/dialogs/common/search_dialog.dart +++ b/lib/layout/dialogs/common/search_dialog.dart @@ -32,8 +32,13 @@ class SearchQueryResult { } class SearchCellDialog extends StatefulWidget { + final String? currentSelection; + final void Function(String value)? onChanged; + @override - State createState() => _SearchCellDialogState(); + State createState() => _SearchCellDialogState(currentSelection: currentSelection); + + SearchCellDialog({this.currentSelection, this.onChanged}) : super(); } final referenceCells = { @@ -44,182 +49,184 @@ final referenceCells = { "mystic_x", }; -class _SearchCellDialogState extends State { - final _searchController = TextEditingController(); - var searchResults = []; - - @override - void initState() { - search(""); - super.initState(); - } - - @override - void dispose() { - _searchController.dispose(); - super.dispose(); - } - - void search(String data) { - final parts = fancySplit(data, ' '); +List handleCellQuery(String data) { + final parts = fancySplit(data, ' '); - final results = []; - final visited = []; + final results = []; + final visited = []; - for (var cat in categories) { - if (cat.title != "Tools") { - for (var item in cat.items) { - if (item is String) { - if (!visited.contains(item)) { - visited.add(item); - results.add(SearchQueryResult(item, cat.title)); - } - } else if (item is CellCategory) { - for (var subitem in item.items) { - if (!visited.contains(subitem)) { - visited.add(subitem); - results.add(SearchQueryResult(subitem, '${cat.title}/${item.title}')); - } + for (var cat in categories) { + if (cat.title != "Tools") { + for (var item in cat.items) { + if (item is String) { + if (!visited.contains(item)) { + visited.add(item); + results.add(SearchQueryResult(item, cat.title)); + } + } else if (item is CellCategory) { + for (var subitem in item.items) { + if (!visited.contains(subitem)) { + visited.add(subitem); + results.add(SearchQueryResult(subitem, '${cat.title}/${item.title}')); } } } } } + } - for (var ref in referenceCells) { - results.add(SearchQueryResult(ref, "References")); - } + for (var ref in referenceCells) { + results.add(SearchQueryResult(ref, "References")); + } - if (parts.first == "") { - searchResults = results; - return; - } + if (parts.first == "") { + return results; + } - final filters = []; + final filters = []; - while (true) { - if (parts.isEmpty) { - break; - } - if (parts.first.startsWith('@')) { - final str = parts.first.substring(1); + while (true) { + if (parts.isEmpty) { + break; + } + if (parts.first.startsWith('@')) { + final str = parts.first.substring(1); - if (str.contains('(') && str.endsWith(')')) { - final i = str.indexOf('('); + if (str.contains('(') && str.endsWith(')')) { + final i = str.indexOf('('); - final name = str.substring(0, i); - final content = str.substring(i + 1, str.length - 1); + final name = str.substring(0, i); + final content = str.substring(i + 1, str.length - 1); - filters.add(SearchFilter(name, content)); - } else { - filters.add(SearchFilter(str, "")); - } - parts.removeAt(0); + filters.add(SearchFilter(name, content)); } else { - break; + filters.add(SearchFilter(str, "")); } + parts.removeAt(0); + } else { + break; } + } - if (parts.isEmpty) { - parts.add(""); + if (parts.isEmpty) { + parts.add(""); + } + + var i = 0; + var descs = []; + while (true) { + if (i >= parts.length) { + break; + } + if (parts[i].startsWith('"') && parts[i].endsWith('"')) { + descs.add(parts.removeAt(i)); + } else { + i++; } + } - var i = 0; - var descs = []; - while (true) { - if (i >= parts.length) { - break; - } - if (parts[i].startsWith('"') && parts[i].endsWith('"')) { - descs.add(parts.removeAt(i)); - } else { - i++; + if (parts.isEmpty) { + parts.add(""); + } + + results.retainWhere((result) { + final desc = idToDesc(result.cell).toLowerCase(); + + for (var d in descs) { + if (desc.contains(d.toLowerCase())) { + return true; } } - if (parts.isEmpty) { - parts.add(""); + return descs.isEmpty; + }); + + final name = parts.join(" "); + if (name.replaceAll(' ', '') != "") { + results.retainWhere( + (result) => idToString( + result.cell, + ).toLowerCase().contains( + name.toLowerCase(), + ), + ); + } + for (var filter in filters) { + if (filter.name == "modded") { + results.retainWhere((result) => result.isModded); + } + if (filter.name == "vanilla") { + results.retainWhere((result) => result.isVanilla); } + if (filter.name == "category" || filter.name == "cat" || filter.name == "categories" || filter.name == "cats") { + final stuff = fancySplit(filter.content, ',').map((e) { + var s = e; + + while (s.startsWith(' ')) { + s = s.substring(1); + } + while (s.endsWith(' ')) { + s = s.substring(0, s.length - 1); + } - results.retainWhere((result) { - final desc = idToDesc(result.cell).toLowerCase(); + if (s.startsWith('"') && s.endsWith('"')) { + s = s.substring(1, s.length - 1); + } - for (var d in descs) { - if (desc.contains(d.toLowerCase())) { - return true; + return s; + }).toList(); + results.retainWhere((result) { + for (var thing in stuff) { + if (result.categoryPath.contains(thing)) { + return true; + } } - } - return descs.isEmpty; - }); - - final name = parts.join(" "); - if (name.replaceAll(' ', '') != "") { - results.retainWhere( - (result) => idToString( - result.cell, - ).toLowerCase().contains( - name.toLowerCase(), - ), - ); + return stuff.isEmpty; + }); } - for (var filter in filters) { - if (filter.name == "modded") { - results.retainWhere((result) => result.isModded); - } - if (filter.name == "vanilla") { - results.retainWhere((result) => result.isVanilla); - } - if (filter.name == "category" || filter.name == "cat" || filter.name == "categories" || filter.name == "cats") { - final stuff = fancySplit(filter.content, ',').map((e) { - var s = e; - while (s.startsWith(' ')) { - s = s.substring(1); - } - while (s.endsWith(' ')) { - s = s.substring(0, s.length - 1); - } + if (filter.name == "mod") { + final stuff = fancySplit(filter.content, ',').map((e) { + var s = e; - if (s.startsWith('"') && s.endsWith('"')) { - s = s.substring(1, s.length - 1); - } + while (s.startsWith(' ')) { + s = s.substring(1); + } + while (s.endsWith(' ')) { + s = s.substring(0, s.length - 1); + } - return s; - }).toList(); - results.retainWhere((result) { - for (var thing in stuff) { - if (result.categoryPath.contains(thing)) { - return true; - } - } + if (s.startsWith('"') && s.endsWith('"')) { + s = s.substring(1, s.length - 1); + } - return stuff.isEmpty; - }); - } + return s; + }).toList(); + results.retainWhere((result) => stuff.every((modStuff) => modStuff.startsWith('"') && modStuff.endsWith('"') ? result.fromModName(modStuff) : result.fromModID(modStuff))); + } + } - if (filter.name == "mod") { - final stuff = fancySplit(filter.content, ',').map((e) { - var s = e; + return results; +} - while (s.startsWith(' ')) { - s = s.substring(1); - } - while (s.endsWith(' ')) { - s = s.substring(0, s.length - 1); - } +class _SearchCellDialogState extends State { + final _searchController = TextEditingController(); + var searchResults = []; + String? currentSelection; - if (s.startsWith('"') && s.endsWith('"')) { - s = s.substring(1, s.length - 1); - } + _SearchCellDialogState({this.currentSelection}) : super(); - return s; - }).toList(); - results.retainWhere((result) => stuff.every((modStuff) => modStuff.startsWith('"') && modStuff.endsWith('"') ? result.fromModName(modStuff) : result.fromModID(modStuff))); - } - } + @override + void initState() { + searchResults = handleCellQuery(""); + super.initState(); + } - searchResults = results; + @override + void dispose() { + _searchController.dispose(); + super.dispose(); } @override @@ -238,7 +245,7 @@ class _SearchCellDialogState extends State { child: TextBox( controller: _searchController, onChanged: (value) { - search(value); + searchResults = handleCellQuery(value); setState(() {}); }, ), @@ -251,6 +258,7 @@ class _SearchCellDialogState extends State { itemCount: searchResults.length, itemBuilder: (ctx, i) { final result = searchResults[i]; + final isSelected = currentSelection == null ? (game.currentSelection == result.cell) : (currentSelection == result.cell); return SizedBox( width: constraints.maxWidth * 0.8, @@ -264,9 +272,13 @@ class _SearchCellDialogState extends State { ), title: Text(idToString(result.cell)), subtitle: Text(idToDesc(result.cell)), - tileColor: game.currentSelection == result.cell ? ConstantColorButtonState(Colors.successPrimaryColor) : ConstantColorButtonState(Colors.grey[130]), + tileColor: isSelected ? ConstantColorButtonState(Colors.successPrimaryColor) : ConstantColorButtonState(Colors.grey[130]), onPressed: () { - game.currentSelection = result.cell; + if(currentSelection == null) { + game.currentSelection = result.cell; + } + currentSelection = result.cell; + widget.onChanged?.call(result.cell); setState(() {}); }, ), @@ -283,7 +295,7 @@ class _SearchCellDialogState extends State { Button( child: Text("Ok"), onPressed: () { - Navigator.pop(context); + Navigator.pop(context, currentSelection); }, ), ], diff --git a/lib/layout/other/version.dart b/lib/layout/other/version.dart index 2ba2e86..67e23f7 100755 --- a/lib/layout/other/version.dart +++ b/lib/layout/other/version.dart @@ -17,6 +17,8 @@ final List changes = [ "Added Area Denial cell and Ticked Bomb", "Improved cell selection menus", "Made boolean properties have the checkbox next to the name in the property editor", + "Used the Cell Search Dialog a lot more to improve cell selecting", + "Added borders to world clearing", ]; IconData getTrailing(String change) {