avm2: Roughly implement `TextField.*IndexAtPoint`
Both implementations currently use `screen_position_to_index`, which is inaccurate, and that's why these methods still produce a stub warning. However, this implementation makes some games work, is a lot better than a perfect implementation which would require a lot of work and time, and infinitely better than no implementation at all.
This commit is contained in:
parent
a9708a8017
commit
a3dddbd80d
|
@ -139,10 +139,7 @@ package flash.text {
|
|||
stub_method("flash.text.TextField", "insertXMLText");
|
||||
}
|
||||
|
||||
public function getCharIndexAtPoint(x:Number, y:Number):int {
|
||||
stub_method("flash.text.TextField", "getCharIndexAtPoint");
|
||||
return 0;
|
||||
}
|
||||
public native function getCharIndexAtPoint(x:Number, y:Number):int;
|
||||
|
||||
public native function getLineLength(lineIndex:int):int;
|
||||
|
||||
|
@ -165,10 +162,7 @@ package flash.text {
|
|||
return null;
|
||||
}
|
||||
|
||||
public function getLineIndexAtPoint(x:Number, y:Number):int {
|
||||
stub_method("flash.text.TextField", "getLineIndexAtPoint");
|
||||
return 0;
|
||||
}
|
||||
public native function getLineIndexAtPoint(x:Number, y:Number):int;
|
||||
|
||||
public native function getLineIndexOfChar(charIndex:int):int;
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ use crate::avm2::Error;
|
|||
use crate::display_object::{AutoSizeMode, EditText, TDisplayObject, TextSelection};
|
||||
use crate::html::TextFormat;
|
||||
use crate::string::AvmString;
|
||||
use crate::{avm2_stub_getter, avm2_stub_setter};
|
||||
use swf::Color;
|
||||
use crate::{avm2_stub_getter, avm2_stub_method, avm2_stub_setter};
|
||||
use swf::{Color, Point};
|
||||
|
||||
pub fn text_field_allocator<'gc>(
|
||||
class: ClassObject<'gc>,
|
||||
|
@ -1469,3 +1469,74 @@ pub fn get_line_index_of_char<'gc>(
|
|||
Ok(Value::Number(-1f64))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_char_index_at_point<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
// TODO This currently uses screen_position_to_index, which is inaccurate, because:
|
||||
// 1. getCharIndexAtPoint should return -1 when clicked outside of a character,
|
||||
// 2. screen_position_to_index returns caret index, not clicked character index.
|
||||
// Currently, it is difficult to prove accuracy of this method, as at the time
|
||||
// of writing this comment, text layout behaves differently compared to Flash.
|
||||
// However, the current implementation is good enough to make some SWFs work.
|
||||
avm2_stub_method!(
|
||||
activation,
|
||||
"flash.text.TextField",
|
||||
"getCharIndexAtPoint",
|
||||
"inaccurate char index detection"
|
||||
);
|
||||
|
||||
let Some(this) = this
|
||||
.as_display_object()
|
||||
.and_then(|this| this.as_edit_text())
|
||||
else {
|
||||
return Ok(Value::Undefined);
|
||||
};
|
||||
|
||||
let x = args.get_f64(activation, 0)?;
|
||||
let y = args.get_f64(activation, 1)?;
|
||||
|
||||
if let Some(index) = this.screen_position_to_index(Point::from_pixels(x, y)) {
|
||||
Ok(index.into())
|
||||
} else {
|
||||
Ok(Value::Number(-1f64))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_line_index_at_point<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
// TODO This currently uses screen_position_to_index, but it should calculate
|
||||
// the line index using only line data, without taking into account characters.
|
||||
// Currently, it is difficult to prove accuracy of this method, as at the time
|
||||
// of writing this comment, text layout behaves differently compared to Flash.
|
||||
avm2_stub_method!(
|
||||
activation,
|
||||
"flash.text.TextField",
|
||||
"getLineIndexAtPoint",
|
||||
"inaccurate line index detection"
|
||||
);
|
||||
|
||||
let Some(this) = this
|
||||
.as_display_object()
|
||||
.and_then(|this| this.as_edit_text())
|
||||
else {
|
||||
return Ok(Value::Undefined);
|
||||
};
|
||||
|
||||
let x = args.get_f64(activation, 0)?;
|
||||
let y = args.get_f64(activation, 1)?;
|
||||
|
||||
if let Some(index) = this
|
||||
.screen_position_to_index(Point::from_pixels(x, y))
|
||||
.and_then(|index| this.line_index_of_char(index))
|
||||
{
|
||||
Ok(index.into())
|
||||
} else {
|
||||
Ok(Value::Number(-1f64))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue