summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/editorui/paths.py112
-rw-r--r--src/unlock.py138
2 files changed, 153 insertions, 97 deletions
diff --git a/src/editorui/paths.py b/src/editorui/paths.py
index 4110188..a0e65d6 100644
--- a/src/editorui/paths.py
+++ b/src/editorui/paths.py
@@ -538,93 +538,6 @@ class KPEditorPath(QtGui.QGraphicsLineItem):
self.setPalette(palette)
- class UnlockButton(QtGui.QPushButton):
- def __init__(self, pathRef):
- QtGui.QPushButton.__init__(self)
-
- self.setFixedSize(48,48)
-
- self.iconList = [QtGui.QIcon("Resources/Key.png"),
- QtGui.QIcon("Resources/SecretKey.png")]
-
- self.unlockIcon = QtGui.QIcon("Resources/Unlock.png")
- self.arrowIcon = [QtGui.QIcon("Resources/KeyArrow.png"),
- QtGui.QIcon("Resources/SecretKeyArrow.png")]
-
-
- self._pathRef = pathRef
-
- self.secret = 0
- self.path = 0
-
- if not hasattr(KPEditorPath.UnlockButton, 'PALETTE'):
- KPEditorPath.UnlockButton.PALETTE = QtGui.QPalette(Qt.transparent)
-
- self.setPalette(self.PALETTE)
-
- self.released.connect(self.toggle)
-
-
- def toggle(self):
-
- path = self._pathRef()
-
- if KP.app.keyboardModifiers() == Qt.ShiftModifier:
- if self.secret == 1:
- self.secret = 0
- else:
- self.secret = 1
-
- path.secret = self.secret
-
- else:
- self.path += 1
-
- if self.path > 2:
- self.path = 0
-
- path.unlocks = self.path
-
-
- def paintEvent(self, event):
- painter = QtGui.QPainter(self)
- contentsRect = self.contentsRect()
- smallRect = QtCore.QRect(12, 12, 24, 24)
- painter.setRenderHint(QtGui.QPainter.SmoothPixmapTransform)
-
- if self.path > 0:
- painter.save()
-
- displaceX, displaceY = contentsRect.width() / 2, contentsRect.height() / 2
-
- pathItem = self._pathRef().qtItem.line()
-
- if self.path == 1:
- angle = 90 - pathItem.angle()
- else:
- angle = 270 - pathItem.angle()
-
- painter.translate(displaceX, displaceY)
- painter.rotate(angle)
- painter.translate(-displaceX, -displaceY)
- self.arrowIcon[self.secret].paint(painter, contentsRect, Qt.AlignCenter)
-
- painter.restore()
-
- if self.isDown():
- self.iconList[self.secret].paint(painter, smallRect, Qt.AlignCenter, QtGui.QIcon.Disabled)
- else:
- self.iconList[self.secret].paint(painter, smallRect, Qt.AlignCenter)
-
- else:
- if self.isDown():
- self.unlockIcon.paint(painter, smallRect, Qt.AlignCenter, QtGui.QIcon.Disabled)
- else:
- self.unlockIcon.paint(painter, smallRect, Qt.AlignCenter)
-
- painter.end()
-
-
class HiddenProxy(QtGui.QGraphicsProxyWidget):
def __init__(self, button, parent, x, y):
QtGui.QGraphicsProxyWidget.__init__(self, parent)
@@ -663,12 +576,6 @@ class KPEditorPath(QtGui.QGraphicsLineItem):
if not hasattr(KPEditorPath, 'SELECTION_PEN'):
KPEditorPath.SELECTION_PEN = QtGui.QPen(Qt.blue, 1, Qt.DotLine)
- self.unlock = self.UnlockButton(self._pathRef)
- self.unlockProxy = self.HiddenProxy(self.unlock, self, -24, -24)
-
- self.unlock.secret = path.secret
- self.unlock.path = path.unlocks
-
self.options = self.PathOptionsMenuButton(self._pathRef)
self.optionsProxy = self.HiddenProxy(self.options, self, -54, +24)
@@ -677,6 +584,20 @@ class KPEditorPath(QtGui.QGraphicsLineItem):
self.updatePosition()
+ def mousePressEvent(self, event):
+ if event.button() != Qt.LeftButton:
+ return
+ if QtGui.QApplication.keyboardModifiers() != QtCore.Qt.ControlModifier:
+ return
+
+ # modify the unlock settings
+ from unlock import KPUnlockSpecDialog
+
+ # todo: set the existing thing there
+ result = KPUnlockSpecDialog.exec_()
+ if result == QtGui.QDialog.Accepted:
+ print "OK!"
+
def updatePosition(self):
path = self._pathRef()
@@ -720,12 +641,9 @@ class KPEditorPath(QtGui.QGraphicsLineItem):
painter.setPen(self.SELECTION_PEN)
painter.setBrush(QtGui.QColor(0,0,0,0))
painter.drawPath(self.shape())
-
- self.unlockProxy.show()
self.optionsProxy.show()
else:
- self.unlockProxy.hide()
self.optionsProxy.hide()
@@ -753,4 +671,4 @@ class KPEditorPath(QtGui.QGraphicsLineItem):
self.scene().removeItem(self)
- \ No newline at end of file
+
diff --git a/src/unlock.py b/src/unlock.py
new file mode 100644
index 0000000..0f954d6
--- /dev/null
+++ b/src/unlock.py
@@ -0,0 +1,138 @@
+import re
+
+LEVEL_RE = re.compile(r'^([0-9]{1,2})-([0-9]{1,2})( secret)?$')
+COMBINER_RE = re.compile(r'[ ]*(and|or)[ ]*')
+
+class UnlockParseError(ValueError):
+ # todo: is this the proper way to make an Error?
+ pass
+
+def parseUnlockText(text):
+ return _parseUnlockBit(text)
+
+def _parseUnlockBit(text):
+ # blank criterion
+ if text == '':
+ return ('always',)
+
+ # is this a simple one...?
+ m = LEVEL_RE.match(text)
+ if m:
+ one, two, secret = m.groups()
+ return ('level', int(one), int(two), (secret != None))
+
+ # OK, let's parse parentheses
+ pLevel = 0
+ endAt = len(text) - 1
+
+ # this could be either AND or OR or nothing at all
+ # we won't know it until we finish parsing!
+ whatCombiner = None
+
+ subTerms = []
+ currentSubTermStart = None
+
+ skip = 0
+
+ for index, char in enumerate(text):
+ if skip > 0:
+ skip -= 1
+ continue
+
+ if char == '(':
+ if pLevel == 0:
+ currentSubTermStart = index
+ pLevel += 1
+ elif char == ')':
+ pLevel -= 1
+ if pLevel < 0:
+ raise UnlockParseError('close parenthesis without a matching open')
+ elif pLevel == 0:
+ subTerms.append((currentSubTermStart, index, text[currentSubTermStart+1:index]))
+ # are we expecting to see something else?
+ if index == endAt: break
+
+ m = COMBINER_RE.match(text, index + 1)
+ if not m:
+ raise UnlockParseError('something unexpected at %d' % (index+1))
+
+ # what is it?
+ nextCombiner = m.group(1)
+ if whatCombiner is not None and nextCombiner != whatCombiner:
+ raise UnlockParseError('mixed %s and %s in one term. use more parentheses!' % (whatCombiner,nextCombiner))
+ whatCombiner = nextCombiner
+
+ # go right past this, to the next subterm
+ skip = len(m.group(0))
+ else:
+ if pLevel == 0:
+ raise UnlockParseError('something unexpected at %d' % index)
+
+ # now that we're here, we must have parsed these subterms
+ # do we have a combiner?
+ if whatCombiner is None:
+ assert len(subTerms) == 1
+
+ return _parseUnlockBit(subTerms[0][2])
+ else:
+ return (whatCombiner, map(lambda x: _parseUnlockBit(x[2]), subTerms))
+
+
+
+if __name__ == '__main__':
+ print repr(parseUnlockText('((01-01 secret) and (01-02)) or (02-99 secret) or (01-01)'))
+
+ from sys import exit
+ exit()
+
+
+
+
+
+from common import *
+
+
+
+
+class KPUnlockSpecDialog(QtGui.QDialog):
+ def __init__(self, forWhat, unlockAdjective):
+ QtGui.QDialog.__init__(self)
+
+ self.setWindowTitle('Set Unlock Criteria')
+
+ text = """You may enter various criteria that must be fulfilled for this {0} to be {1}.<br>
+ <br>
+ Here are some examples of what you can use:
+ <ul>
+ <li>01-01 - <i>a single criterion</i></li>
+ <li>01-01 secret - <i>secret exits</i></li>
+ <li>(01-01 secret) and (01-02) - <i>combine two criteria</i></li>
+ <li>((01-01 secret) or (01-02)) and (01-04) - <i>nested criteria</i></li>
+ </ul>
+ Each criterion used on the sides of AND and OR must be surrounded by parentheses.<br>
+ <br>
+ To leave this {0} permanently unlocked, leave the box blank.
+ """.format(forWhat, unlockAdjective)
+
+ self.label = QtGui.QLabel(text)
+ self.label.setWordWrap(True)
+
+ self.textBox = QtGui.QLineEdit()
+ self.textBox.textChanged.connect(self.checkInputValidity)
+
+ self.buttons = QtGui.QDialogButtonBox(
+ QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
+
+ self.buttons.accepted.connect(self.accept)
+ self.buttons.rejected.connect(self.reject)
+
+ self.layout = QtGui.VBoxLayout()
+ self.layout.addWidget(self.label)
+ self.layout.addWidget(self.textBox)
+ self.layout.addWidget(self.buttons)
+ self.setLayout(self.layout)
+
+ def checkInputValidity(self, text):
+ self.parsed = parseUnlockText(text)
+ self.buttons.button(QtGui.QDialogButtonBox.Ok).setEnabled(not (self.parsed is None))
+