Add command visualizers for /execute, /setblock, /clone
This commit is contained in:
parent
5e273b1235
commit
f43e5e0bc6
203
src/mcedit2/rendering/command_visuals.py
Normal file
203
src/mcedit2/rendering/command_visuals.py
Normal file
@ -0,0 +1,203 @@
|
||||
"""
|
||||
command_visuals
|
||||
"""
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
import logging
|
||||
|
||||
from OpenGL import GL
|
||||
|
||||
from mcedit2.rendering.scenegraph.depth_test import DepthFuncNode
|
||||
from mcedit2.rendering.scenegraph.misc import LineWidthNode
|
||||
from mcedit2.rendering.scenegraph.scenenode import Node
|
||||
from mcedit2.rendering.scenegraph.vertex_array import VertexNode
|
||||
from mcedit2.rendering.selection import SelectionBoxNode
|
||||
from mcedit2.rendering.vertexarraybuffer import VertexArrayBuffer
|
||||
from mcedit2.util.commandblock import UnknownCommand
|
||||
from mceditlib.geometry import Vector
|
||||
from mceditlib.selection import BoundingBox
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def LineStripNode(points, rgba):
|
||||
vertexArray = VertexArrayBuffer(len(points), GL.GL_LINE_STRIP, False, False)
|
||||
vertexArray.vertex[:] = points
|
||||
vertexArray.rgba[:] = rgba
|
||||
node = VertexNode([vertexArray])
|
||||
return node
|
||||
|
||||
arcSegments = 20
|
||||
def LineArcNode(p1, p2, color):
|
||||
rgba = [c * 255 for c in color]
|
||||
points = [p1]
|
||||
x, y, z = p1
|
||||
dx = p2[0] - p1[0]
|
||||
dz = p2[2] - p1[2]
|
||||
dx /= arcSegments
|
||||
dz /= arcSegments
|
||||
# heightDiff = p1[1] - p2[1]
|
||||
# maxRise = 8
|
||||
|
||||
# initial y-velocity
|
||||
dy = 0.5
|
||||
|
||||
# the height of p2 without gravity
|
||||
|
||||
overshot = y + dy * arcSegments - p2[1]
|
||||
|
||||
# needed gravity so the last point is p2
|
||||
ddy = -overshot / (arcSegments * (arcSegments-1) / 2)
|
||||
|
||||
for i in range(arcSegments):
|
||||
y += dy
|
||||
dy += ddy
|
||||
x += dx
|
||||
z += dz
|
||||
points.append((x, y, z))
|
||||
|
||||
arcNode = Node()
|
||||
|
||||
lineNode = LineStripNode(points, rgba)
|
||||
|
||||
lineWidthNode = LineWidthNode(3.0)
|
||||
lineWidthNode.addChild(lineNode)
|
||||
|
||||
arcNode.addChild(lineWidthNode)
|
||||
|
||||
depthNode = DepthFuncNode(GL.GL_GREATER)
|
||||
depthNode.addChild(lineNode)
|
||||
|
||||
arcNode.addChild(depthNode)
|
||||
|
||||
return arcNode
|
||||
|
||||
|
||||
|
||||
def CommandVisuals(pos, commandObj):
|
||||
visualCls = _visualClasses.get(commandObj.name)
|
||||
if visualCls is None:
|
||||
log.warn("No command found for %s", commandObj.name)
|
||||
return Node()
|
||||
else:
|
||||
return visualCls(pos, commandObj)
|
||||
|
||||
class SetBlockVisuals(Node):
|
||||
commandName = "setblock"
|
||||
|
||||
def __init__(self, pos, commandObj):
|
||||
super(SetBlockVisuals, self).__init__()
|
||||
|
||||
x, y, z = commandObj.resolvePosition(pos)
|
||||
|
||||
color = (0.2, 0.9, 0.7, 0.6)
|
||||
|
||||
boxNode = SelectionBoxNode()
|
||||
boxNode.filled = False
|
||||
boxNode.wireColor = color
|
||||
boxNode.selectionBox = BoundingBox((x, y, z), (1, 1, 1))
|
||||
|
||||
lineNode = LineArcNode(Vector(*pos) + (0.5, 0.5, 0.5), (x+.5, y+.5, z+.5), color)
|
||||
|
||||
self.addChild(boxNode)
|
||||
self.addChild(lineNode)
|
||||
|
||||
class CloneVisuals(Node):
|
||||
commandName = "clone"
|
||||
|
||||
def __init__(self, pos, commandObj):
|
||||
super(CloneVisuals, self).__init__()
|
||||
|
||||
sourceBox = commandObj.resolveSourceBounds(pos)
|
||||
|
||||
dest = commandObj.resolveDestination(pos)
|
||||
destBox = BoundingBox(dest, sourceBox.size)
|
||||
|
||||
sourceColor = (0.2, 0.4, 0.9, 0.6)
|
||||
destColor = (0.0, 0.0, 0.9, 0.6)
|
||||
|
||||
sourceBoxNode = SelectionBoxNode()
|
||||
sourceBoxNode.filled = False
|
||||
sourceBoxNode.wireColor = sourceColor
|
||||
sourceBoxNode.selectionBox = sourceBox
|
||||
|
||||
destBoxNode = SelectionBoxNode()
|
||||
destBoxNode.filled = False
|
||||
destBoxNode.wireColor = destColor
|
||||
destBoxNode.selectionBox = destBox
|
||||
|
||||
lineToSourceNode = LineArcNode(Vector(*pos) + (0.5, 0.5, 0.5), sourceBox.center, sourceColor)
|
||||
lineToDestNode = LineArcNode(sourceBox.center, destBox.center, destColor)
|
||||
|
||||
self.addChild(sourceBoxNode)
|
||||
self.addChild(destBoxNode)
|
||||
|
||||
self.addChild(lineToSourceNode)
|
||||
self.addChild(lineToDestNode)
|
||||
|
||||
|
||||
class ExecuteVisuals(Node):
|
||||
commandName = "execute"
|
||||
|
||||
def __init__(self, pos, commandObj):
|
||||
"""
|
||||
|
||||
Parameters
|
||||
----------
|
||||
commandObj : ExecuteCommand
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
||||
"""
|
||||
super(ExecuteVisuals, self).__init__()
|
||||
|
||||
selector = commandObj.targetSelector
|
||||
if selector.playerName is not None:
|
||||
return
|
||||
|
||||
selectorPos = [selector.getArg(a) for a in 'xyz']
|
||||
|
||||
if None in (selectorPos):
|
||||
log.warn("No selector coordinates for command %s", commandObj)
|
||||
targetPos = commandObj.resolvePosition((0, 0, 0))
|
||||
else:
|
||||
targetPos = commandObj.resolvePosition(selectorPos)
|
||||
|
||||
# Draw box at selector pos and draw line from command block to selector pos
|
||||
# xxxx selector pos is a sphere of radius `selector.getArg('r')`
|
||||
|
||||
boxNode = SelectionBoxNode()
|
||||
boxNode.filled = False
|
||||
boxNode.wireColor = (0.9, 0.2, 0.2, 0.6)
|
||||
boxNode.selectionBox = BoundingBox(selectorPos, (1, 1, 1))
|
||||
|
||||
lineNode = LineArcNode(Vector(*pos) + (0.5, 0.5, 0.5),
|
||||
Vector(*selectorPos) + (.5, .5, .5),
|
||||
(0.9, 0.2, 0.2, 0.6))
|
||||
self.addChild(boxNode)
|
||||
self.addChild(lineNode)
|
||||
|
||||
if selectorPos != targetPos:
|
||||
# Command block's own coordinates are different from the selected pos,
|
||||
# either relative or absolute.
|
||||
# Draw a box at the target coordinates and a line from
|
||||
# the selected pos to the target
|
||||
|
||||
boxNode = SelectionBoxNode()
|
||||
boxNode.filled = False
|
||||
boxNode.wireColor = (0.9, 0.2, 0.2, 0.6)
|
||||
boxNode.selectionBox = BoundingBox(targetPos, (1, 1, 1))
|
||||
|
||||
lineNode = LineArcNode(Vector(*selectorPos) + (0.5, 0.5, 0.5),
|
||||
Vector(*targetPos) + (.5, .5, .5),
|
||||
(0.9, 0.2, 0.2, 0.6))
|
||||
|
||||
self.addChild(boxNode)
|
||||
self.addChild(lineNode)
|
||||
|
||||
if not isinstance(commandObj.subcommand, UnknownCommand):
|
||||
subvisuals = CommandVisuals(targetPos, commandObj.subcommand)
|
||||
self.addChild(subvisuals)
|
||||
|
||||
_visualClasses = {cls.commandName: cls
|
||||
for cls in [ExecuteVisuals,SetBlockVisuals,CloneVisuals]}
|
Reference in New Issue
Block a user