From 84c56e54648d2bcbb119c2adbe3a778c822f3e66 Mon Sep 17 00:00:00 2001 From: xjy Date: Sun, 8 Jun 2025 17:27:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=20/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 中国版碰撞箱座位预览.js | 300 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 中国版碰撞箱座位预览.js diff --git a/中国版碰撞箱座位预览.js b/中国版碰撞箱座位预览.js new file mode 100644 index 0000000..8190325 --- /dev/null +++ b/中国版碰撞箱座位预览.js @@ -0,0 +1,300 @@ +/** + * @author JannisX11 + * @modified by 芥子 + * @date 2024年11月30日 + * @improvement 更改了碰撞箱的计算方式可以直接得出max/min,json文本改为中国版可用的格式可以直接复制粘贴,并汉化了一下。 + */ +/// + +(function() { + let scale = 1; + let position = [0, 0, 0]; + let rotation = 0; + let new_version = true; + + + window.SeatPositioner = { + getDialogLines() { + return [ + `
+ + +
`, + `
+ + +
`, + `
+ + + + + + + + +
`, + `
+ +
` + ] + }, + dialog: new Dialog({ + id: 'seat_position', + title: '座位位置预览', + width: 540, + lines: [], + singleButton: true, + onConfirm: function() { + scene.remove(SeatPositioner.object); + this.hide() + } + }), + object: new THREE.Object3D(), + setupObject: function() { + + if (SeatPositioner.init) return; + + var O = SeatPositioner.object; + var M = new THREE.MeshLambertMaterial({color: 0xffffff}); + + var head = new THREE.Mesh(new THREE.BoxGeometry(8, 8, 8), M); + head.position.y = 19; + O.add(head); + + var body = new THREE.Mesh(new THREE.BoxGeometry(8, 12, 4), M); + body.position.y = 9; + O.add(body); + + var leg_geo = new THREE.BoxGeometry(); + leg_geo.setShape([-2, -12, -2], [2, 0, 2]); + + var leg_r = new THREE.Mesh(leg_geo, M); + leg_r.position.set(2, 3, 0); + leg_r.rotation.x = Math.degToRad(70); + leg_r.rotation.z = Math.degToRad(13); + O.add(leg_r); + + var leg_l = new THREE.Mesh(leg_geo, M); + leg_l.position.set(-2, 3, 0); + leg_l.rotation.x = Math.degToRad(70); + leg_l.rotation.z = Math.degToRad(-13); + O.add(leg_l); + + var arm_geo = new THREE.BoxGeometry(); + arm_geo.setShape([-2, -10, -2], [2, 2, 2]); + + var arm_r = new THREE.Mesh(arm_geo, M); + arm_r.position.set(6, 13, 0); + arm_r.rotation.x = Math.degToRad(36); + O.add(arm_r); + + var arm_l = new THREE.Mesh(arm_geo, M); + arm_l.position.set(-6, 13, 0); + arm_l.rotation.x = Math.degToRad(36); + O.add(arm_l); + + SeatPositioner.init = true; + }, + update: function() { + let output = ''; + + position[0] = trimFloatNumber(parseFloat($('#STP-px').val())||0); + position[1] = trimFloatNumber(parseFloat($('#STP-py').val())||0); + position[2] = trimFloatNumber(parseFloat($('#STP-pz').val())||0); + + new_version = $('#STP-v').is(':checked'); + SeatPositioner.object.position.set( + position[0] * -16, + position[1] * 16 + (new_version ? 2.2 : 0), + position[2] * -16, + ); + output = `"position": [${position.join(', ')}]`; + + scale = parseFloat( $('#STP-s').val() )||0 + var s = 1 / scale; + SeatPositioner.object.scale.set(s, s, s); + + rotation = parseFloat( $('#STP-r').val() )||0; + SeatPositioner.object.rotation.y = -Math.degToRad(rotation); + if (rotation) { + output += `, "rotate_rider_by": ${trimFloatNumber(rotation)}` + } + + $('#STP-out').val(output); + + } + }; + + + window.SetupHitboxHelper = { + dialog: new Dialog({ + id: 'setup_hitbox', + title: '中国版碰撞箱预览', + width: 540, + form: { + type: {label: '模式', type: 'select', options: { + entity_hitbox: '生物射线碰撞箱', + entity_collision: '生物实体碰撞箱', + block_selection_box: '方块射线碰撞箱', + block_collision: '方块实体碰撞箱', + }}, + size_entity: {label: '大小', type: 'vector', value: [1, 1], dimensions: 2, step: 0.1, condition: form => form.type == 'entity_hitbox' || form.type == 'entity_collision'}, + offset_entity: {label: '偏移', type: 'vector', value: [0, 0, 0], step: 0.1, condition: form => form.type == 'entity_hitbox'}, + size_block: {label: '大小', type: 'vector', value: [16, 16, 16], max: 16, min: 0, dimensions: 3, condition: form => form.type.startsWith('block')},//方块初始显示 + offset_block: {label: '偏移', type: 'vector', value: [-8, 0, 8], condition: form => form.type.startsWith('block')}, + result: {type: 'textarea', height: 130, readonly: true} + }, + singleButton: true, + //生物碰撞箱 + onFormChange({type, size_entity, size_block, offset_entity, offset_block}) { + if (type.startsWith('entity')) { + SetupHitboxHelper.object.scale.x = SetupHitboxHelper.object.scale.z = size_entity[0] || 0.01; + SetupHitboxHelper.object.scale.y = size_entity[1] || 0.01; + SetupHitboxHelper.object.position.fromArray(offset_entity).multiplyScalar(16); + SetupHitboxHelper.object.position.set( + -offset_entity[0] * 16, + offset_entity[1] * 16, + -offset_entity[2] * 16 + ); + } else { + SetupHitboxHelper.object.scale.x = size_block[0]/16 || 0.01; + SetupHitboxHelper.object.scale.z = size_block[2]/16 || 0.01; + SetupHitboxHelper.object.scale.y = size_block[1]/16 || 0.01; + SetupHitboxHelper.object.position.set( + -offset_block[0], + offset_block[1], + offset_block[2] + ); + } + + let result_string; + if (type == 'entity_hitbox') { + // Entity + result_string = '"minecraft:custom_hit_test": '+ compileJSON({ + "hitboxes": [ + { + width: size_entity[0], + height: size_entity[1], + pivot: [offset_entity[0], offset_entity[1] + size_entity[1]/2, offset_entity[2]] + } + ] + }) + } else if (type == 'entity_collision') { + // Entity + result_string = '"minecraft:collision_box": '+ compileJSON({ + width: size_entity[0], + height: size_entity[1], + }) + } else { + // Block + let value = compileJSON({ + max: [1-(offset_block[0] - size_block[0]/2 + 8 + size_block[0] +8)/16+size_block[0]/16, (size_block[1]+offset_block[1])/16,(offset_block[2] - size_block[2]/2 + 8 + size_block[2]-8)/16], + min: [1-(offset_block[0] - size_block[0]/2 + 8 +8)/16-size_block[0]/16, offset_block[1]/16, (offset_block[2] - size_block[2]/2 + 8 -8)/16] + //origin: [offset_block[0] - size_block[0]/2, offset_block[1], offset_block[2] - size_block[2]/2], + //size: size_block + });16 + + if (size_block.allEqual(0)) value = false; + if (size_block.allEqual(16) && offset_block.allEqual(0)) value = true; + + result_string = "方块模型规范:面朝N所指方向,红蓝线交点作方块的左上角,方块模型需要从这里开始,向右下角伸展。\n"+`"${type == 'block_collision' ? 'collision' : 'clip'}": ` + value + } + $('dialog#setup_hitbox textarea').val(result_string).addClass('code'); + }, + onOpen() { + if (!this.getFormResult().type?.endsWith('block') && Format.id == 'bedrock_block') { + setTimeout(() => { + this.setFormValues({type: 'block_collision'}); + }, 10); + } + }, + onConfirm() { + scene.remove(SetupHitboxHelper.object); + this.hide() + } + }), + size: [1, 0], + offset: [0, 0, 0], + object: null, + setupObject: function() { + + if (SetupHitboxHelper.init) return; + let object = SetupHitboxHelper.object = new THREE.LineSegments( + new THREE.BufferGeometry(), + new THREE.LineBasicMaterial({color: 0xffbd2e}) + ) + let position_array = [ + 8, 0, 8, 8, 16, 8, + 8, 0, -8, 8, 16, -8, + -8, 0, 8, -8, 16, 8, + -8, 0, -8, -8, 16, -8, + + 8, 0, 8, -8, 0, 8, + 8, 0, -8, -8, 0, -8, + 8, 16, 8, -8, 16, 8, + 8, 16, -8, -8, 16, -8, + + 8, 0, 8, 8, 0, -8, + -8, 0, 8, -8, 0, -8, + 8, 16, 8, 8, 16, -8, + -8, 16, 8, -8, 16, -8, + ] + object.geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(position_array), 3)); + object.geometry.attributes.position.needsUpdate = true; + SetupHitboxHelper.init = true; + } + }; + + var seat_pos_action, hitbox_action, style; + + Plugin.register('中国版碰撞箱座位预览', { + title: '中国版碰撞箱座位预览', + icon: 'event_seat', + author: '芥子(原作者JannisX11)', + description: '适用于中国版的载具座位,生物/方块的射线碰撞箱实体碰撞箱预览工具。\n原作者开源地址:https://github.com/JannisX11/blockbench-plugins/tree/master/plugins/seat_position.js', + tags: ["Minecraft: Bedrock Edition"], + version: '1.0.4', + variant: 'both', + onload() { + seat_pos_action = new Action('open_seat_position', { + name: '设置座椅位置', + icon: 'event_seat', + condition: _ => Format.bone_rig, + click: () => { + SeatPositioner.dialog.lines = SeatPositioner.getDialogLines(); + SeatPositioner.dialog.show(); + $('#blackout').hide(0); + SeatPositioner.setupObject(); + scene.add(SeatPositioner.object); + } + }) + hitbox_action = new Action('open_hitbox_setup', { + name: '设置碰撞箱', + description: '设置实体或方块的射线碰箱或实体碰撞箱', + icon: 'view_in_ar', + condition: _ => Format.bone_rig, + click: () => { + SetupHitboxHelper.dialog.show(); + $('#blackout').hide(0); + SetupHitboxHelper.setupObject(); + scene.add(SetupHitboxHelper.object); + SetupHitboxHelper.dialog.updateFormValues(); + } + }) + MenuBar.addAction(seat_pos_action, 'filter'); + MenuBar.addAction(hitbox_action, 'filter'); + + style = Blockbench.addCSS(` + dialog#setup_hitbox textarea { + tab-size: 40px; + } + `) + }, + onunload() { + seat_pos_action.delete(); + hitbox_action.delete(); + } + }) + +})()