--*********************************************************** --** THE INDIE STONE ** --*********************************************************** require('ISUI/ISScrollingListBox') require('Vehicles/ISUI/ISUI3DScene') local FONT_HGT_SMALL = getTextManager():getFontHeight(UIFont.Small) local FONT_HGT_MEDIUM = getTextManager():getFontHeight(UIFont.Medium) AnimationClipViewer = ISPanel:derive("AnimationClipViewer") ----- AnimationClipViewer_ListBox = ISScrollingListBox:derive("AnimationClipViewer_ListBox") local ListBox = AnimationClipViewer_ListBox function ListBox:prerender() ISScrollingListBox.prerender(self) local clipName = self.items[self.selected] and self.items[self.selected].text if clipName and (clipName ~= self.selectedClipName) then self.selectedClipName = clipName self.parent.scene.javaObject:fromLua2("setCharacterAnimationClip", "character1", clipName) end end function ListBox:doDrawItem(y, item, alt) if y + self:getYScroll() + self.itemheight < 0 or y + self:getYScroll() >= self.height then return y + self.itemheight end return ISScrollingListBox.doDrawItem(self, y, item, alt) end function ListBox:onMouseDown(x, y) ISScrollingListBox.onMouseDown(self, x, y) end function ListBox:indexOf(text) for i,item in ipairs(self.items) do if item.text == text then return i end end return -1 end function ListBox:new(x, y, width, height) local o = ISScrollingListBox.new(self, x, y, width, height) return o end ----- AnimationClipViewer_OptionsPanel = ISPanel:derive("AnimationClipViewer_OptionsPanel") local OptionsPanel = AnimationClipViewer_OptionsPanel function OptionsPanel:createChildren() local tickBox = ISTickBox:new(10, 10, 300, 500, "", self, self.onTickBox) tickBox:initialise() self:addChild(tickBox) local gameState = getAnimationViewerState() for i=1,gameState:getOptionCount() do local option = gameState:getOptionByIndex(i-1) tickBox:addOption(option:getName(), option) tickBox:setSelected(i, option:getValue()) end tickBox:setWidthToFit() self.tickBox = tickBox end function OptionsPanel:onTickBox(index, selected) local option = self.tickBox.optionData[index] option:setValue(selected) if option:getName() == "DrawGrid" then self.parent.scene.javaObject:fromLua1("setDrawGrid", selected) end if option:getName() == "Isometric" then self.parent:resetView() end if option:getName() == "UseDeferredMovement" then self.parent.scene.javaObject:fromLua2("setCharacterUseDeferredMovement", "character1", selected) end end function OptionsPanel:onMouseDownOutside(x, y) if self:isMouseOver() then return end self:setVisible(false) -- self:removeFromUIManager() end function OptionsPanel:new(x, y, width, height) local o = ISPanel.new(self, x, y, width, height) o.backgroundColor.a = 0.8 return o end ----- AnimationClipViewer_Scene = ISUI3DScene:derive("AnimationClipViewer_Scene") local Scene = AnimationClipViewer_Scene function Scene:prerenderEditor() self.javaObject:fromLua1("setGizmoVisible", "none") self.javaObject:fromLua1("setGizmoOrigin", "none") if not self.zeroVector then self.zeroVector = Vector3f.new() end self.javaObject:fromLua1("setGizmoPos", self.zeroVector) self.javaObject:fromLua1("setGizmoRotate", self.zeroVector) self.javaObject:fromLua0("clearAABBs") self.javaObject:fromLua0("clearAxes") self.javaObject:fromLua1("setSelectedAttachment", nil) end function Scene:prerender() ISUI3DScene.prerender(self) end function Scene:onMouseDown(x, y) ISUI3DScene.onMouseDown(self, x, y) local gameState = getAnimationViewerState() self.rotate = not isKeyDown(Keyboard.KEY_LSHIFT) end function Scene:onMouseMove(dx, dy) if self.rotate then local current = self.javaObject:fromLua0("getViewRotation") local rx = current:x() + 0 local ry = current:y() + dx / 2 local rz = current:z() + 0 if getAnimationViewerState():getBoolean("Isometric") then rx = 30 rz = 0 end self.javaObject:fromLua3("setViewRotation", rx, ry, rz) return end ISUI3DScene.onMouseMove(self, dx, dy) end function Scene:onMouseUp(x, y) ISUI3DScene.onMouseUp(self, x, y) self.rotate = false end function Scene:onMouseUpOutside(x, y) self:onMouseUp() end function Scene:onRightMouseDown(x, y) end function Scene:new(x, y, width, height) local o = ISUI3DScene.new(self, x, y, width, height) return o end ----- AnimationClipViewer_Timeline = ISPanel:derive("AnimationClipViewer_Timeline") local Timeline = AnimationClipViewer_Timeline function Timeline:render() ISPanel.render(self) local scene = self.parent.parent.scene local time = scene.javaObject:fromLua1("getCharacterAnimationTime", "character1") local duration = scene.javaObject:fromLua1("getCharacterAnimationDuration", "character1") if not time or not duration then return end if self.parent.parent.listBox.selectedClipName ~= self.selectedClipName then self.selectedClipName = self.parent.parent.listBox.selectedClipName self.keyframeTimes = scene.javaObject:fromLua2("getCharacterAnimationKeyframeTimes", "character1", self.keyframeTimes) end local times = self.keyframeTimes for i=1,times:size() do self:drawRect(self.width * times:get(i-1) / duration, 0, 1, self.height, 1.0, 0.5, 0.5, 0.5) end self:drawRect(self.width * time / duration, 0, 1, self.height, 1.0, 1.0, 1.0, 1.0) end function Timeline:onMouseDown(x, y) local scene = self.parent.parent.scene local duration = scene.javaObject:fromLua1("getCharacterAnimationDuration", "character1") if not duration then return end local xFraction = x / self.width self.parent.parent.animate = false scene.javaObject:fromLua2("setCharacterAnimate", "character1", false) scene.javaObject:fromLua2("setCharacterAnimationTime", "character1", duration * xFraction) self.dragging = true self:setCapture(true) end function Timeline:onMouseMove(dx, dy) if not self.dragging then return end local scene = self.parent.parent.scene local duration = scene.javaObject:fromLua1("getCharacterAnimationDuration", "character1") if not duration then return end local xFraction = self:getMouseX() / self.width xFraction = math.max(xFraction, 0.0) xFraction = math.min(xFraction, 1.0) scene.javaObject:fromLua2("setCharacterAnimationTime", "character1", duration * xFraction) end function Timeline:onMouseMoveOutside(dx, dy) self:onMouseMove(dx, dy) end function Timeline:onMouseUp(x, y) self.dragging = false self:setCapture(false) end function Timeline:onMouseUpOutside(x, y) self.dragging = false self:setCapture(false) end function Timeline:new(x, y, width, height) local o = ISPanel.new(self, x, y, width, height) o.borderColor.a = 0.0 return o end ----- function AnimationClipViewer:createChildren() local gameState = getAnimationViewerState() self.scene = Scene:new(0, 0, self.width, self.height) self.scene:initialise() self.scene:instantiate() self.scene:setAnchorRight(true) self.scene:setAnchorBottom(true) self:addChild(self.scene) self:resetView() if gameState:getBoolean("Isometric") then self.scene.javaObject:fromLua2("dragView", 0, self.height / 4) else self.scene.javaObject:fromLua2("dragView", 0, self.height / 3) end self.scene.javaObject:fromLua1("setMaxZoom", 20) self.scene.javaObject:fromLua1("setZoom", 7) self.scene.javaObject:fromLua1("setGizmoScale", 1.0 / 5.0) self.scene.javaObject:fromLua1("setDrawGrid", gameState:getBoolean("DrawGrid")) self.scene.javaObject:fromLua1("setDrawGridAxes", true) self.scene.javaObject:fromLua1("setGridPlane", "XZ") self.scene.javaObject:fromLua1("createCharacter", "character1") self.scene.javaObject:fromLua2("setCharacterAlpha", "character1", 1.0) self.scene.javaObject:fromLua2("setCharacterAnimate", "character1", self.animate) self.scene.javaObject:fromLua2("setCharacterAnimSet", "character1", "player-editor") self.scene.javaObject:fromLua2("setCharacterState", "character1", "runtime") self.scene.javaObject:fromLua2("setCharacterClearDepthBuffer", "character1", false) self.scene.javaObject:fromLua2("setCharacterShowBones", "character1", false) self.scene.javaObject:fromLua2("setCharacterUseDeferredMovement", "character1", gameState:getBoolean("UseDeferredMovement")) self.scene.javaObject:fromLua2("setObjectVisible", "character1", true) self:createToolbar() local bottomH = 100 self.filter = ISTextEntryBox:new("", 10, 10, 250, FONT_HGT_MEDIUM + 2 * 2) self.filter.font = UIFont.Medium self:addChild(self.filter) self.filter:setClearButton(true) local listY = self.filter:getBottom() + 4 local listBox = ListBox:new(10, listY, 250, self.height - bottomH - 10 - listY) listBox:setAnchorBottom(true) self:addChild(listBox) listBox:setFont(UIFont.Small, 2) self.listBox = listBox self:setClipList() self.bottomPanel = ISPanel:new(0, self.height - bottomH, self.width, bottomH) self.bottomPanel:setAnchorTop(false) self.bottomPanel:setAnchorLeft(false) self.bottomPanel:setAnchorRight(false) self.bottomPanel:setAnchorBottom(true) self.bottomPanel:noBackground() self:addChild(self.bottomPanel) local timeline = Timeline:new(10, 0, self.width - 10 * 2, 50) self.bottomPanel:addChild(timeline) self.timeline = timeline self.speedScale = ISSliderPanel:new(self.width / 2 - 400 / 2, self.bottomPanel.y - 30, 400, 20, self, self.onSpeedScaleChanged) self.speedScale.anchorTop = false self.speedScale.anchorBottom = true self.speedScale:setValues(0.0, 5.0, 0.1, 1.0) self.speedScale:setCurrentValue(1.0, true) self:addChild(self.speedScale) local buttonHgt = FONT_HGT_MEDIUM + 8 local button2 = ISButton:new(10, self.bottomPanel.height - 10 - buttonHgt, 80, buttonHgt, "EXIT", self, self.onExit) self.bottomPanel:addChild(button2) end function AnimationClipViewer:createToolbar() local toolHgt = 30 self.toolBar = ISPanel:new(0, 10, 300, toolHgt) self.toolBar:noBackground() self:addChild(self.toolBar) local button = ISButton:new(0, 0, 60, toolHgt, "OPTIONS", self, self.onOptions) self.toolBar:addChild(button) self.buttonOptions = button self.toolBar:setWidth(button:getRight()) self.toolBar:setX(self.width / 2 - self.toolBar.width / 2) self.optionsPanel = OptionsPanel:new(0, 0, 300, 400) self.optionsPanel:setVisible(false) self:addChild(self.optionsPanel) end function AnimationClipViewer:onSpeedScaleChanged(speed, slider) end function AnimationClipViewer:resetView() self.scene:setView("UserDefined") local gameState = getAnimationViewerState() if gameState:getBoolean("Isometric") then self.scene.javaObject:fromLua3("setViewRotation", 30.0, 45.0, 0.0) self.scene.javaObject:fromLua1("setGridPlane", "XZ") else self.scene.javaObject:fromLua3("setViewRotation", 0.0, 0.0, 0.0) self.scene.javaObject:fromLua1("setGridPlane", "XY") end end function AnimationClipViewer:setClipList() self.listBox:clear() local filterText = string.trim(self.filter:getInternalText()) local clips = getAnimationViewerState():fromLua0("getClipNames") for i=1,clips:size() do local clipName = clips:get(i-1) if string.contains(string.lower(clipName), filterText) then self.listBox:addItem(clipName, clipName) end end end function AnimationClipViewer:onResolutionChange(oldw, oldh, neww, newh) self:setWidth(neww) self:setHeight(newh) self.bottomPanel:setX(self.width / 2 - self.bottomPanel.width / 2) self.speedScale:setX(self.width / 2 - self.speedScale.width / 2) end function AnimationClipViewer:update() ISPanel.update(self) if self.width ~= getCore():getScreenWidth() or self.height ~= getCore():getScreenHeight() then self:onResolutionChange(self.width, self.height, getCore():getScreenWidth(), getCore():getScreenHeight()) end local filterText = string.trim(self.filter:getInternalText()) if self.filterText ~= filterText then self.filterText = filterText self:setClipList() end local speed = self.speedScale:getCurrentValue() self.scene.javaObject:fromLua2("setCharacterAnimationSpeed", "character1", speed) end function AnimationClipViewer:prerender() ISPanel.prerender(self) self.scene:prerenderEditor() self.scene.javaObject:fromLua6("addAxis", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) end function AnimationClipViewer:render() ISPanel.render(self) local time = self:getCurrentTime() local duration = self:getDuration() local text = string.format("SECONDS: %.2f / %.2f", time, duration) self:drawText(text, self.width / 2 - 150, self.height - 30, 1.0, 1.0, 1.0, 1.0, UIFont.Medium) text = string.format("FRACTION: %.2f", time / duration) self:drawText(text, self.width / 2 + 50, self.height - 30, 1.0, 1.0, 1.0, 1.0, UIFont.Medium) local frame = self:getCurrentFrame() local lastFrame = self:getLastFrame() text = string.format("FRAME: %d / %d", math.min(frame, lastFrame), lastFrame) self:drawText(text, self.width / 2 + 200, self.height - 30, 1.0, 1.0, 1.0, 1.0, UIFont.Medium) text = string.format("SpeedScale: %.2f", self.speedScale:getCurrentValue()) self:drawText(text, self.speedScale.x, self.speedScale.y - 8 - FONT_HGT_MEDIUM, 1.0, 1.0, 1.0, 1.0, UIFont.Medium) end function AnimationClipViewer:onKeyPress(key) local fps = self:getFPS() if key == Keyboard.KEY_LEFT then local time = self:getCurrentTime() local frame = self:getCurrentFrame() - 1 if time * fps - frame > 0.1 then frame = frame + 1 end self.scene.javaObject:fromLua2("setCharacterAnimationTime", "character1", math.max(frame - 1, 0) / fps) end if key == Keyboard.KEY_RIGHT then local time = self:getCurrentTime() local frame = self:getCurrentFrame() - 1 local lastFrame = self:getLastFrame() self.scene.javaObject:fromLua2("setCharacterAnimationTime", "character1", math.min(frame + 1, lastFrame - 1) / fps) end if key == Keyboard.KEY_SPACE then self.animate = not self.animate self.scene.javaObject:fromLua2("setCharacterAnimate", "character1", self.animate) end end function AnimationClipViewer:getFPS() return 30 end function AnimationClipViewer:getDuration() return self.scene.javaObject:fromLua1("getCharacterAnimationDuration", "character1") or 1.0 end function AnimationClipViewer:getCurrentTime() return self.scene.javaObject:fromLua1("getCharacterAnimationTime", "character1") or 0.0 end function AnimationClipViewer:getCurrentFrame() local fps = self:getFPS() local time = self:getCurrentTime() return math.floor(time * fps + 0.01) + 1 end function AnimationClipViewer:getLastFrame() local fps = self:getFPS() local duration = self:getDuration() return luautils.round(duration * fps) + 1 end function AnimationClipViewer:onOptions() self.optionsPanel:setX(self.buttonOptions:getAbsoluteX()) self.optionsPanel:setY(self.buttonOptions:getAbsoluteY() + self.buttonOptions:getHeight()) self.optionsPanel:setVisible(true) end function AnimationClipViewer:onExit(button, x, y) getAnimationViewerState():fromLua0("exit") end -- Called from Java function AnimationClipViewer:showUI() end function AnimationClipViewer:new(x, y, width, height) local o = ISPanel.new(self, x, y, width, height) o:setAnchorRight(true) o:setAnchorBottom(true) o:noBackground() o:setWantKeyEvents(true) o.animate = true getAnimationViewerState():setTable(o) return o end -- Called from Java function AnimationViewerState_InitUI() local UI = AnimationClipViewer:new(0, 0, getCore():getScreenWidth(), getCore():getScreenHeight()) AnimationViewerState_UI = UI UI:setVisible(true) UI:addToUIManager() end